在进一步学习计算属性之前,让我们先深入的了解一些Vue的实例。
提示:原理/底层,理解难度大,面试易涉及……
在Vue实例化时,我们传入了一个选项对象,其属性除了我们已经学过的el和data,还可以有:
比如:created、 mounted、updated、destroyed……
var vm = new Vue({ el: "#yz-hello", data: { students: ['夏康平', '陈国栋', '韩佳宝'] }, created: function(){ console.log('I was created'); }, mounted: function () { console.log('I was mounted'); }, updated: function () { console.log('I was updated'); } })这些都是函数,内容由开发人员自定义,他们会在Vue实例初始化的某些个特定阶段被执行。他们又被称之为钩子(hook)函数。
演示:
我们把一个对象从生成(new)到被销毁(destroy)的过程,称之为生命周期。
学习Vue实例的生命周期,实际上就是学习:一个Vue对象,从创建到被销毁,它究竟干了些什么。在现目前阶段,我们稍微简化一下:
实例化一个Vue的JavaScript对象,在JavaScript语言内部为接下来的DOM渲染做准备。
该阶段以调用钩子函数:created结束。
演示:在created中设置断点,查看
通过el获取模板,根据模板和vue data生成DOM元素,然后将其挂载到原HTML页面(渲染)。
该阶段以调用钩子函数:mounted结束。
演示:在mounted中设置断点,查看:HTML页面被渲染
@想一想@:使用Ajax获取数据的代码,放在created还是mounted里面好?
当vue监控(watch)到vue data发生变动,需要重新(响应式)渲染,渲染完成后会触发钩子函数:updated。
演示:updated不会再次created或mounted
顾名思义,如标题。
但问题是:什么情况下Vue实例才会被销毁呢?
@试一试@:
document.getElementById('yz-hello').remove()
要演示vm的实例的销毁,我们需要:
vm.$destroy()
PS:更多内容参考vue文档完整图
Vue为我们提供了这种内置的,属于Vue实例的属性和方法。
以$开头,主要是为了和开发人员自定义的:
data: { students: ['夏康平', '陈国栋', '韩佳宝'] }, methods: { //和data、钩子函数并列 greet: function () { return "Hello, 源栈"; } },methods中定义的方法可以
vm.greet()
<h1>{{greet()}}</h1>
相区别。
F12控制台演示:
vm.$el vm.$options.el vm.$options.data() vm.$data
当你把一个普通的 JavaScript 对象传入 Vue 实例作为 data 选项,Vue 将遍历此对象所有的 property,并使用 Object.defineProperty 把这些 property 全部转为 getter/setter
控制台演示:
var fg = {} //空对象 Object.defineProperty(fg, 'name', { value: '飞哥' })
还可以传入一个setter 函数,当属性值被修改时,会调用此函数。
Object.defineProperty(fg, 'name', { set: function (value) { console.log('set is called,and value is: ' + value); } });
这些 getter/setter 对用户来说是不可见的,但是在内部它们让 Vue 能够追踪依赖,在 property 被访问和修改时通知变更。
简单的理解:有了getter/setter,才能在赋值的时候添加逻辑(又被称之为:数据劫持)。
@想一想@:为什么不直接用obj.Property=XXX呢?
code is everything。
在Vue.js上设置断点,5901行:
function createElm (该方法会在渲染生成HTML元素时使用,查看调用堆栈:
function Vue (options) //Vue实例构造函数 Vue.prototype.$mount = function ( //将生成的element挂载(mount)到DOM树 var Watcher = function Watcher ( //Watcher类 Vue.prototype._update = function (vnode, hydrating) { //更新节点
断点设置在1053行:
function defineReactive$$1 ( //1014行 var dep = new Dep(); Object.defineProperty(obj, key, { set: function reactiveSetter (newVal) { dep.notify();
然后更新vue data。
为了便于演示,我们把vue data独立出来:
var objGreet = { greet: "Hello, 源栈" };
var vm = new Vue({ el: "#yz-hello", data: objGreet,
这时候我们可以使用Object.freeze()方法“冻结”住vue data:
//Object.freeze(objGreet);
演示:略
基于上述知识,我们知道,Vue实例会在初始化时遍历vue data属性,然后予以监控(watch)。
因为Vue只会被实例化一次,所以,之后添加到vue data的属性,Vue是不能予以监控的,所以就没有响应式的效果。
比如:vue data里添加一个slagon:
var objGreet = { slagon: { } };
模板里显示slagon.description
<p>{{slagon.description}}</p>
F12控制台演示:objGreet.description='hello,源栈' 无效。
为了解决这个问题,Vue给我们提供了一个内置的set()方法:
vm.$set(objGreet.slagon, 'description', 'hello,源栈') //实例方法或者,我们也可以使用Vue的全局/静态方法:
Vue.set(objGreet.slagon, 'description', 'hello,源栈')
两者是一样的。
set()方法还可以用于数组
vm.$set(students, 0, '飞哥') //用下标0代替属性名
演示:略
PS:在备课时发现,如果先用等号赋值(=)的方式给objGreet.description赋值,再用set()就无效了,/笑哭.jpg
你可能已经注意到了:description是slagon而不是objGreet的属性,能不能省略这个objGreet呢?
不行!因为:
根级响应式 property你必须在初始化实例前声明所有,哪怕只是一个空值。
演示:set()添加vue data根级属性报错……
但vue官方建议是将所有要使用的vue data都事先声明,这样:
为了更好的开发体验:vue官方建议安装Vue-devtools插件。
演示:安装完成后效果
多快好省!前端后端,线上线下,名师精讲
更多了解 加: