# 前言 本文非vue教程,僅為學習vue過程中的個人理解與筆記,有說的不正確的地方歡迎指正討論# 1、computed計算屬性函數中不能使用vm變數在計算屬性的函數中,不能使用Vue構造函數返回的vm變數,因為此時vm還未返回,依然處於Vue內部構造函數過程中,遂只能使用this來代替vm。若要使... ...
前言
本文非vue教程,僅為學習vue過程中的個人理解與筆記,有說的不正確的地方歡迎指正討論
1、computed計算屬性函數中不能使用vm變數
在計算屬性的函數中,不能使用Vue構造函數返回的vm變數,因為此時vm還未返回,依然處於Vue內部構造函數過程中,遂只能使用this來代替vm。
若要使用typescript
,可使用以下方法來實現代碼智能感知
vm = vm || this;
另:其他不能用vm變數,只能使用this變數的地方,都可以通過此方法來獲得Typescript的智能感知和代碼語法檢查,比如mounted
生命周期系列函數等。
不過模板里的vm引用Typescript無能為力,只能等待ts支持vue的jsx語法了╮(╯_╰)╭
2、計算屬性中不能引用其他計算屬性?
官方教程中沒有找到相關說明(應該是我沒找到),從使用角度而言大致可以總結出以下結論:
1、計算屬性必須引用(依賴)非計算屬性或固定值。(見demo1)
2、計算屬性若引用(依賴)其他計算屬性,則被引用的計算屬性必須引用非計算屬性或固定值(見demo2)
3、計算屬性可迴圈依賴,但最終依賴鏈上的最上游的計算屬性,必須引用非計算屬性或固定值。
DEMO1:官方標準用法,計算屬性引用非計算屬性:
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
}
}
});
原因很容易理解,如果最終沒有引用或依賴任何非計算屬性,那麼計算屬性在計算時會陷入死迴圈。
3、vue2.0中若使用組件嵌套,則在父組件執行\$forceUpdate()之前模板中\$children為空數組
觸發這個問題有以下幾個前提:
1、vue版本為2.0版本,1.0無此問題。
2、使用組件嵌套,在父組件的模板中訪問$children
變數
3、在渲染完成後沒有再將$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",
});
如下圖:

解決方案1:使用\$forceUpdate()
註冊父組件的mounted
方法,執行$forceUpdate()
<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正確了:

解決方案2:使用vm的變數代替\$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版本的源碼才能瞭解了。
4、若父組件的template或render函數中無引用slot元素,則\$children恆等於空數組
此問題關聯上面第3個問題。
觸發此問題的前提:
1、vue2.0版本
2、父組件和子組件都直接寫在調用方模板中
3、在模板中訪問$children
變數
4、已經解決在上述問題3中強制刷新的問題
復現代碼:
<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"
});

解決方案1:父組件模板包含slot元素
在父組件的模板中加入slot
元素。或在render函數中引用了this.$slots.default
變數
Vue.component("parent", {
template: "<p>parent child:{{$children.length}} <slot></slot></p>",
mounted(){
this.$forceUpdate();
}
});

解決方案2:在父組件模板中編寫子組件定義
此解決方案要修改此問題的復現第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>
相關筆記
Vue學習筆記-1(http://www.cnblogs.com/xxcanghai/p/5849038.html)
Vue學習筆記-2(http://www.cnblogs.com/xxcanghai/p/6098663.html)