键盘敲烂,月薪过万作业不做,等于没学
当前系列: Vue.js 修改讲义

在进一步学习计算属性之前,让我们先深入的了解一些Vue的实例。

提示:原理/底层,理解难度大,面试易涉及……

在Vue实例化时,我们传入了一个选项对象,其属性除了我们已经学过的el和data,还可以有:


实例生命周期钩子

比如:createdmountedupdateddestroyed……

        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)函数。

演示:

  1. 交换钩子函数的位置,观察他们的执行顺序是否变化
  2. 更改vm.student,updated被触发


生命周期

我们把一个对象从生成(new)到被销毁(destroy)的过程,称之为生命周期

学习Vue实例的生命周期,实际上就是学习:一个Vue对象,从创建到被销毁,它究竟干了些什么。在现目前阶段,我们稍微简化一下:

初始化:init

实例化一个Vue的JavaScript对象,在JavaScript语言内部为接下来的DOM渲染做准备。

该阶段以调用钩子函数:created结束。

演示:在created中设置断点,查看

  • 未被渲染的HTML页面
  • 控制台vm.students

挂载:mount

通过el获取模板,根据模板和vue data生成DOM元素,然后将其挂载到原HTML页面(渲染)。

该阶段以调用钩子函数:mounted结束。

演示:在mounted中设置断点,查看:HTML页面被渲染

@想一想@:使用Ajax获取数据的代码,放在created还是mounted里面好?

更新:update

当vue监控(watch)到vue data发生变动,需要重新(响应式)渲染,渲染完成后会触发钩子函数:updated。

演示:updated不会再次created或mounted

销毁:destroyed

顾名思义,如标题。

但问题是:什么情况下Vue实例才会被销毁呢?

@试一试@

  • document.getElementById('yz-hello').remove()
  • 或者,重新加载页面?……

要演示vm的实例的销毁,我们需要:

vm.$destroy()

PS:更多内容参考vue文档完整图


实例属性和方法

Vue为我们提供了这种内置的,属于Vue实例的属性和方法。

以$开头,主要是为了和开发人员自定义的:

  • data中的属性(复习)
  • methods中的方法:
    data: {
        students: ['夏康平', '陈国栋', '韩佳宝']
    },
    methods: {  //和data、钩子函数并列
        greet: function () {
            return "Hello, 源栈";
        }
    },
    methods中定义的方法可以
    • 直接由vm实例调用
      vm.greet()
    • 在template中使用
      <h1>{{greet()}}</h1>

相区别。

F12控制台演示:

vm.$el
vm.$options.el
vm.$options.data()
vm.$data


响应式原理

复习:效果

Object.defineProperty()

当你把一个普通的 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,

freeze()

在某些特殊情况下,我们可能想禁用掉Vue的响应式功能。

这时候我们可以使用Object.freeze()方法“冻结”住vue data:

//Object.freeze(objGreet);

演示:略

set()

基于上述知识,我们知道,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都事先声明,这样:

  1. 给vue的追踪一个边界
  2. 为以后使用TypeScript留下空间
  3. 代码可读/可维护


安装vue-devtools插件

为了更好的开发体验:vue官方建议安装Vue-devtools插件

演示:安装完成后效果


作业

  1. 在Vue.js中找到:
    1. 钩子函数在哪里被设置,在哪里被调用?
    2. set()方法的定义,并解释为什么:
      1. 调用set()方法就能将新添加的属性纳入“响应式”?
      2. 为什么用等号赋值方式添加一个vue data属性之后,再使用set()就无效了?
  2. 安装成功vue-devtools
学习笔记
源栈学历
键盘敲烂,月薪过万作业不做,等于没学

作业

觉得很 ,不要忘记分享哟!

任何问题,都可以直接加 QQ群:273534701

在当前系列 Vue.js 中继续学习:

多快好省!前端后端,线上线下,名师精讲

  • 先学习,后付费;
  • 不满意,不要钱。
  • 编程培训班,我就选源栈

更多了解 加:

QQ群:273534701

答疑解惑,远程debug……

B站 源栈-小九 的直播间

写代码要保持微笑 (๑•̀ㅂ•́)و✧

公众号:源栈一起帮

二维码