方案 B
直接替换整个 data 结果
View.vue
<template>
<div>
<div>
<div @click="watchedMethod">{{name}}</div>
<div @click="watchedMethod">{{$data.unwatch}}</div>
<div>{{$data.onlyGet}}</div>
<div @click="$data.cMethod">cMethod</div>
</div>
</div>
</template>
<script>
import { Controller } from "./Controller";
export default {
data(vc) {
console.log(vc);
return new Controller(vc);
},
mounted() {
this.$data.mount();
}
};
</script>
Controller.vue 如下:
export class Controller<T = any>
{
name = `This is a Controller's name`; // 普通的属性
private pivateValue = '_pValue'; // 私有的属性,由于只是 ts 的语法糖,同样会被 vue 复制到 VueComponent 转 getter 和 setter 属性
_unwatch = '_unwatch'; // 私有属性,vue 不会把 _开头的属性复制到 VueComponent, 不会和 vue 的私有属性冲突
_ctx: T; // 上下文属性,VueComponent 实例,可以方便的调用 $开头的的方法。
constructor(ctx: T)
{
this._ctx = ctx;
}
get unwatch() { return this._unwatch };
set unwatch(val) { this._unwatch = val };
watchedMethod = (e: any) =>
{
console.log(` A controller do something ${e}`)
}
mount = () => console.log('c mounted');
get onlyGet() { return `only get` }
cMethod(e: any)
{
console.log(`cMethid:${e}`)
}
}
方案 B 结果分析:
优点:
- controller 可以有私有属性,以 _ 开头即可;
- controller 的方法不会被观察
- controller 可以自由扩展(继承,实现接口等等)
- controller 的一级属性在 vue 中可以直接使用 缺点:
- controller 的方法在 vue 中不可直接用, 使用 $data.f() 可以解决
结语
方案 B 相对于 方案 A 优点更多,可以在不修改脚手架情况下使用,并且能充分发挥 vue 的作用,目前还比较满意,后续有更好的方案会再补充比较。