baidu / san-ssr

San SSR framework and utils
https://baidu.github.io/san-ssr/
37 stars 20 forks source link

computed 中的 this 用起来很奇怪 #43

Closed harttle closed 4 years ago

harttle commented 4 years ago

computed 中可以使用 this.data.get('foo') 但不能使用 this. 其他属性/方法(见 文档:计算属性)。更基本的一个问题是,

是否允许 computed 里访问实例属性、方法。

harttle commented 4 years ago

类似 #42

harttle commented 4 years ago

补充一个 this 比较有用的case:

class XComponent extends Component {
    name() {
        const f = this.data.get('firstName')
        const l = this.data.get('lastName')
        return `${f} ${l}`
    }
    computed = {
        upperName() {
            return this.name().toUppercase()
        }
        lowerName() {
            return this.name().toLowercase()
        }
    }
}
errorrik commented 4 years ago

是否允许 computed 里访问实例属性、方法

不允许。一个是保持干净,computed的职责就应该是字面表达的意思。一个是实现层面,需要依赖分析

只能获取数据,那么 computed 就应该接受一个参数 getData

确实,getData是更纯粹的抽象。之前的考虑点是,和正常的数据获取方法保持一致。而且getData其实不符合目前api设计的调性。各有利弊

qiansc commented 4 years ago

我倾向于在ESNEXT和TS里,computed、filters里尽量不用this,也不获取外部变量,尽量通过传参解决。 当然如果这样去做,模板也会有相当多的非纯函数的filters的使用会变成computed,而filters将会是纯函数,可以模板用,也可以供computed使用。 如果参照这样去实践,不会break现有的api,需要做的是给computed加形参,不知道这样做有没有什么利弊?

class XComponent extends Component {
    computed = {
        upperName(data) {
            return data.get('firstName').toUppercase()
        }
        lowerName(data) {
            return name(data.get('firstName'), data.get('lastName')).toLowercase()
        }
    }
}

function name(firstName, lastName) {
        return `${firstName} ${lastName}`
}
harttle commented 4 years ago

computed 方法中,this 的类型按照 { data: { get: (path: string) => any } } 来实现。