本文非vue教程,仅为学习vue过程当中的我的理解与笔记,有说的不正确的地方欢迎指正讨论html
在计算属性的函数中,不能使用Vue构造函数返回的vm变量,由于此时vm还未返回,依然处于Vue内部构造函数过程当中,遂只能使用this来代替vm。
若要使用typescript
,可以使用如下方法来实现代码智能感知vue
vm = vm || this;
另:其余不能用vm变量,只能使用this变量的地方,均可以经过此方法来得到Typescript的智能感知和代码语法检查,好比mounted
生命周期系列函数等。
不过模板里的vm引用Typescript无能为力,只能等待ts支持vue的jsx语法了╮(╯_╰)╭typescript
官方教程中没有找到相关说明(应该是我没找到),从使用角度而言大体能够总结出如下结论:数组
DEMO1:官方标准用法,计算属性引用非计算属性:app
var vm = new Vue({ el: "#app", data: { dataVal: "xxcanghai" }, computed: { computedVal1: function () { //标准用法,计算属性引用非计算属性 return this.dataVal + "_1";//输出 xxcanghai_1 } } });
DEMO2:计算属性链式依赖其余计算属性,则依赖链头必须引用非计算属性或固定值函数
var vm = new Vue({ el: "#app", data: { dataVal: "xxcanghai" }, computed: { computedVal1: function () { return this.dataVal + "_1"; }, computedVal2: function () { //合法,计算属性computedVal2引用computedVal1,computedVal1再引用dataVal return this.computedVal1 + "_2";//输出 xxcanghai_1_2 } } });
缘由很容易理解,若是最终没有引用或依赖任何非计算属性,那么计算属性在计算时会陷入死循环。学习
触发这个问题有如下几个前提:this
$children
变量$children
变量写入过父组件的data
变量(或其余vm数据)<!--父组件HTML模板--> <div id="app"> <div>{{$children.length}}</div> <!--此处显示0,应该为3--> <child></child> <child></child> <child></child> </div> //子组件代码 Vue.component("child", { template: "<div>child</div>", }); //父组件声明 new Vue({ el: "#app", });
以下图:
3d
注册父组件的mounted
方法,执行$forceUpdate()
code
<div id="app"> <div>{{$children.length}}</div> <child></child> <child></child> <child></child> </div> Vue.component("child", { template: "<div>child</div>", }); new Vue({ el: "#app", mounted: function () { this.$forceUpdate();//强制从新绘制 } });
$children正确了:

注册父组件的mounted
方法,将$children
赋值给自定义的vm的变量。
同时模板中使用自定义的变量来代替默认的$children
<div id="app"> <div>{{child.length}}</div> <!--使用自定义的child对象--> <child></child> <child></child> <child></child> </div> Vue.component("child", { template: "<div>child</div>", }); var vm = new Vue({ el: "#app", data: { child: [] }, mounted: function () { this.child = this.$children;//手动将$children对象赋值给自定义child变量 } });

至于致使此问题的缘由只能经过阅读vue2.0版本的源码才能了解了。
此问题关联上面第3个问题。
触发此问题的前提:
$children
变量复现代码:
<div id="app"> <!--子组件直接写在调用方的模板中--> <parent> <child></child> <child></child> <child></child> </parent> </div> //父组件 Vue.component("parent", { template: "<p>parent child:{{$children.length}} </p>",//模板中无slot元素 mounted(){ this.$forceUpdate(); } }); Vue.component("child", { template: "<div>child</div>" }); var vm = new Vue({ el: "#app" });

在父组件的模板中加入slot
元素。或在render函数中引用了this.$slots.default
变量
Vue.component("parent", { template: "<p>parent child:{{$children.length}} <slot></slot></p>", mounted(){ this.$forceUpdate(); } });

此解决方案要修改此问题的复现第2要素,即子组件定义从调用方改成写到父组件的模板中也可解决此问题。
<div id="app"> <parent> </parent> </div> Vue.component("parent", { //直接在父组件中写明调用子组件标签 template: "<p>parent child:{{$children.length}}\ <child></child>\ <child></child>\ </p>", mounted(){ this.$forceUpdate(); } }); Vue.component("child", { template: "<div>child</div>", }); var vm = new Vue({ el: "#app", data: { child: [] } });

此方法虽然能够解决问题,可是有时咱们直接把子组件写在调用方会更方便更利于理解,好比Tab与TabPage组件。
以下Tab组件代码,可能更符合通常人的使用思惟:
<div id="app"> <tab> <tab-page>Page1</tab-page> <tab-page>Page2</tab-page> <tab-page>Page3</tab-page> </tab> </div>