2020-07-02 初稿 2021-04-29 补充
公司用 ts 写 vue 项目,经过初步的了解记录在此。
重新开始
我们先通过一个全新项目来尝试 ts,通过 vue create ts-vue-demo
再创建过程中选择 ts
初始化之后,看到新增两个依赖:
vue-class-component
vue-property-decorator
几个开发依赖:
@vue/cli-plugin-typescript
@vue/eslint-config-typescript
typescript
vue-template-combiler
其中 vue-class-component
是 vuejs
官方推出的。
vue-class-component
这里摘录官方的代码,看看怎么用
// 固定写法,分别引入 Vue Component
import Vue from 'vue'
import Component from 'vue-class-component'
// 装饰器,本质上是一个函数
@Component({
props: {
propMessage: String
}
})
// class Name 是 App
export default class App extends Vue {
// initial data
msg = 123
// use prop values for initial data
helloMsg = 'Hello, ' + this.propMessage
// lifecycle hook
mounted () {
this.greet()
}
// computed 变成了 get
get computedMsg () {
return 'computed ' + this.msg
}
// method
greet () {
alert('greeting: ' + this.msg)
}
}
看完官方的demo感觉并不复杂,后续有通过基类继承
import Component,{mixins} from 'vue-class-component'
@Component
export class MyComp extends minxins(MyMixin){}
看到这里,github used27.8k star4.2k
从短暂的考察成都来看,官方维护 vue-class-component
还不够强大,实际中使用 vue-property-decorator
更多,作为替代品。
vue-property-decorator
这个是民间维护的,官方推荐的插件。它完全依赖 vue-class-compnent
这个插件提供了几个装饰器和 mixin 函数
@Prop
@PropSync
@Model
@Watch
@Provide
@Inject
@ProvideReactive
@InjectReactive
@Emit
@Ref
后两者继承自 vue-class-compnent
:
@Component
Mixins
先看代码 Prop
// 这里一行代码引入 Vue Componet 和 Prop
impornt { Vue, Component, Prop } from 'vue-property-decorator'
@Component
export defalut class _name_ extends Vue {
@Prop(Number) readonly propA: string
@Prop({ defalut: '' }) readonly propB!:string
}
有一种情况是,通过 prop 获得数据,在页面里 computed 部分使用。
https://github.com/kaorun343/vue-property-decorator
vue2 vue3中的 provide/injdect
provide/inject 的使用不必多说。options/class-component/composition 三种用法。
- 优点显而易见:祖先组件一旦注入,下游的子代孙代随时能获取到数据,也能修改数据,操作数据更直观。
- 缺点,数据耦合,组件难复用。
- 如何避免?双刃剑,组件库、插件、整体的一个业务组件可以使用,更能体现数据“高内聚”。
无论在 vue2 还是 vue3 里,对于 provide/indect
,官方的表述是一致的:绑定的值不是响应式的。
vue2 里的表述
提示:provide 和 inject 绑定并不是可响应的。这是刻意为之的。然而,如果你传入了一个可监听的对象,那么其对象的 property 还是可响应的。 https://cn.vuejs.org/v2/api/#provide-inject
vue3 里的表述
默认情况下,provide/inject 绑定并不是响应式的。我们可以通过传递一个 ref property 或 reactive 对象给 provide 来改变这种行为。 https://v3.cn.vuejs.org/guide/component-provide-inject.html#%E5%A4%84%E7%90%86%E5%93%8D%E5%BA%94%E6%80%A7
vue3 中单独把 reactive
功能单独拆分成api,这让 reactive-provide 变得更为容易。官方案例独立成章节来讨论
vue2 里如何操作?如何理解“如果你传入一个可监听的对象”?
翻看一些帮助连接能够看到答案:
// 祖先组件
@Component({
components: {
HelloWorld,
},
})
export default class App extends Vue {
public data1 = { a: 1 };
@Provide()
public provideData = this.data1;
}
// 子组件
@Component
export default class HelloWorld extends Vue {
@Prop() private msg!: string;
@Inject()
public provideData!: any;
public changeInject(): void {
this.provideData.a = 2;
}
}
做了demo,效果是ok的。
包括 vue-property-decorator 中的 ReactiveProvide
源码 https://github.com/kaorun343/vue-property-decorator/blob/master/src/helpers/provideInject.ts#L28
思路都是 data中设定数据,provide引用 data
Vue.utils.defineReactive
战未来:composition-api
忘了他吧,使用 @vue/composition-api