Vue学习笔记-2
目录
前言
本文非 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、计算属性中不能引用其他计算属性?
官方教程中没有找到相关说明 (应该是我没找到),从使用角度而言大致可以总结出以下结论:
- 计算属性必须引用(依赖)非计算属性或固定值。(见 demo1)
- 计算属性若引用(依赖)其他计算属性,则被引用的计算属性必须引用非计算属性或固定值(见 demo2)
- 计算属性可循环依赖,但最终依赖链上的最上游的计算属性,必须引用非计算属性或固定值。
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 为空数组
触发这个问题有以下几个前提:
- vue 版本为 2.0 版本,1.0 无此问题。
- 使用组件嵌套,在父组件的模板中访问
$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",
});
如下图:
解决方案 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 个问题。
触发此问题的前提:
- vue2.0 版本
- 父组件和子组件都直接写在调用方模板中
- 在模板中访问
$children
变量 - 已经解决在上述问题 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)