Vue 构造函数、生命周期与数据双向绑定

Vue2 构造函数、生命周期与数据双向绑定

Vue是一个响应式的、渐进式的JavaScript框架,它在设计上采用MVVM模式,将视图与数据两部分分离。下面就是一个简单的Vue实例:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
    {{ message }}
</div>
<script>
    var app=new Vue({
        el:"#app",
        data:{
            message:"Hello Vue!"
        }
    })
</script>
</body>
</html>

可以打开浏览器的控制台,改变app.message的值,可以看到页面上的视图显示部分也会相应的更新。

(1)通过Vue构造函数函数来创建Vue实例

 var app = new Vue({

 })

变量app就是指这个Vue实例。
在Vue实例中,el选项是必须的,el用于指定一个页面上已存在的DOM元素来挂载Vue实例,例如:

<div id="app"></div>
<script>
    var app=new Vue({
        el:"#app",
    })
</script>

之后可以通过app.$el来访问这个被挂载的元素。

  console.log(app.$el)
  //<div id="app"></div>

(2)实例的生命周期钩子函数

每个Vue实例创建时,都会经历一系列初始化的过程,同时也会调用相应的生命周期钩子函数。比较常用的有:

1.created

实例创建完成后调用,在这个阶段完成了数据的观测等,但尚未挂载,$el还不可用。

2.mounted

el挂载到实例上之后调用。

3.beforeDestroyed

实例销毁之前调用。主要解绑一些使用addEventListener监听的事件等。

这些生命周期钩子函数与data类似,也可以写入Vue实例内,并且生命周期钩子函数内的this指向的是调用它的Vue实例。

 var app=new Vue({
        el:"#app",
        data:{
            a:"Hello Vue!"
        },
        created:function(){
            console.log(this.a);
            //Hello Vue!
        },
        mounted:function () {
            console.log(this.$el);
            //<div id="app">
            // Hello Vue!
            // </div>
        }
    });

不要在选项属性或回调上使用箭头函数,比如 created: () => console.log(this.a)。

ES6中提到:在箭头函数中没有自己的this对象,导致内部的this就是外层代码的this。
所以,个人理解在选项属性或回调上使用箭头函数,此时的this指向的是全局属性:

   var app=new Vue({
        el:"#app",
        data:{
            a:"Hello Vue!"
        },
        created:()=>{
            console.log(this.a);
            //undefined
        },
        mounted:()=> {
            console.log(this.$el);
            //undefined
        }
    });
    var a=123;
    var $el=456;
    var app=new Vue({
        el:"#app",
        data:{
            a:"Hello Vue!"
        },
        created:()=>{
            console.log(this.a);
            //123
        },
        mounted:()=> {
            console.log(this.$el);
            //456
        }
    });

(3)数据的双向绑定

Vue实现了数据的双向绑定,通过Vue内的data选项,声名需要绑定的数据。

    var app=new Vue({
        el:"#app",
        data:{
            a:"Hello Vue!"
        }
    });

Vue本身也代理了data对象里面的所有属性,所以对于以上代码,data中的a属性,可以通过app.a进行访问:

    console.log(app.a)
    //Hello Vue!

除了显式的声名数据,也可以指向一个已有的变量,并且它们之间默认建立了双向绑定,当修改其中一个时,另一个也会变化。

    let test={
        a:"Hello Vue!"
    };
    var app=new Vue({
        el:"#app",
        data:test,
    });

    console.log(app.a);
    //Hello Vue!

    app.a="Hello World!";
    console.log(test.a);
    //Hello World!

    test.a="Hello simple!";
    console.log(app.a);
    //Hello simple!

需要注意只有当实例被创建时存在的属性才是响应式的:

    let test = {
        a: "Hello Vue!"
    };
    var app = new Vue({
        el: "#app",
        data: test,
    });
    
    test.b = 1;
    console.log(test.b);//1
    console.log(app.b);//undefined

上面代码中,在Vue实例被创建时,对象中只有属性a,之后在Vue实例创建完成后,给obj添加属性b,这时属性b不是响应式的。

1.双大括号的文本插值
<div id="app">
    {{ message }}
</div>
<script>
    var app=new Vue({
        el:"#app",
        data:{
            message:"Hello Vue!"
        }
    })
</script>

双大括号会被替换成Vue实例上的data对象上的message属性的值。无论何时,只要绑定的数据对象上的message属性的值发生了改变,插值处的内容都会被更新。
比如下面的例子,实时显示当前时间,每秒更新:

<div id="app">
    {{ a }}
</div>
<script>

    var app = new Vue({
        el: "#app",
        data: {
            a: new Date()
        },
        mounted: function () {
            var _this = this;
            this.timer = setInterval(function () {
                _this.a = new Date();
            }, 1000);
        },
        beforeDestroy: function () {
            if (this.timer) {
                clearInterval(this.timer);
            }
        }
    });
</script>

setTimeout()与setInterval()调用的代码运行在与所在函数完全分离的执行环境上。也就是说,setTimeout()与setInterval()代码中包含的 this 关键字会指向 window (或全局)对象。所以需要声明一个_this变量,用来保证setInterval()可以改变Vue实例中的a的值。

显示{{}},不进行替换

如果想显示{{}}标签,而不进行替换,可以使用v-pre,就可以跳过这个元素和它的子元素的编译过程。

<div id="app">
    <div>{{a}}
        <sapn>{{b}}</sapn>
    </div>
    <div v-pre>{{a}}
        <sapn>{{b}}</sapn>
    </div>
</div>
<script>

    var app = new Vue({
        el: "#app",
        data: {
            a: "你好!",
            b: "Hello!"
        },
    });
</script>

渲染结果为:

<div id="app">
    <div>你好!
        <sapn>Hello!</sapn>
    </div>
    <div>{{a}}
        <sapn>{{b}}</sapn>
    </div>
</div>
2.HTML代码插值

如果有时候想输出HTML代码,可以使用v-html:

<div id="app">
    <div v-html="a"></div>
</div>
<script>

    var app = new Vue({
        el: "#app",
        data: {
            a: "<span>你好!</span>"
        },
    });
</script>

渲染后的结果为:

<div id="app">
    <div><span>你好!</span></div>
</div>
3.双大括号中表达式插值

在{{}}中,除了绑定属性值外,还可以使用Javascript表达式进行简单的运算、三元运算等:

<div id="app">
    <div>{{message+1}}</div>
    <div>{{right ? "yes":"no"}}</div>
    <div>{{string+" world!"}}</div>
</div>
<script>
    var app = new Vue({
        el: "#app",
        data: {
            message: 1,
            right: true,
            string:"hello"
        },
    })
</script>

渲染结果为:

<div id="app">
    <div>2</div>
    <div>yes</div>
    <div>hello world!</div>
</div>
4.过滤器

可以在{{}}插值的尾部添加一个管道符号"|",对数据进行过滤。过滤的规则通过给Vue实例添加filters选项来设置:

<div id="app">
    <div>{{a|toUp}}</div>
</div>
<script>
    var app = new Vue({
        el: "#app",
        data: {
            a: "aBcdeFg"
        },
        filters: {
            toUp: function (value) {//这里的value是a数据本身
                return value.toUpperCase();
            }
        }
    });
</script>

上面的代码中,通过过滤器,将字符串中的字母都变为大写。
渲染结果为:

<div id="app">
    <div>ABCDEFG</div>
</div>

过滤器可以串联,也可以接收除了数据本身以外的参数:

 <div>{{a|filter1|filter2}}</div>
 <div>{{a|filter("arg1","arg2")}}</div>

传入"arg1"和"arg2"将作为传递给过滤器的第二和第三个参数,因为过滤器的第一个参数是数据本身。
要注意过滤器属于简单的转换,要实现更复杂的数据处理,应该使用下一篇文章中介绍的计算属性。

5.Object.freeze()阻止修改现有的属性

Object.freeze()使冻结的对象不能添加、修改属性,也不能删除某个属性:

    var obj={
        a: 1
    };
    Object.freeze(obj);
    
    obj.a=11;
    console.log(obj.a);//1
    
    obj.b=2;
    console.log(obj.b);//undefined
    
    delete obj.a;
    console.log(obj.a);//1
在Vue中使用Object.freeze()

没有冻结对象时:

  var app = new Vue({
        el: "#app",
        data: {
            a: 1
        }
    });
    console.log(app.a);//1
    app.a=11;
    console.log(app.a);//11

使用Object.freeze()冻结对象之后,修改app.a的值会报错:

   var app = new Vue({
        el: "#app",
        data: Object.freeze({
            a: 1
        }),
    });

    console.log(app.a);//1
    app.a=11;
    //Uncaught TypeError: Cannot assign to read only property 'a' of object '#<Object>'
冻结已有变量
    var obj={
        a: 1
    };
    Object.freeze(obj);
    var app = new Vue({
       el: "#app",
       data:obj,
   });
    console.log(app.a);//1
    obj.a=2;
    console.log(app.a);//1

在这里,我发现了一个比较好玩的事情,把 Object.freeze(obj)放在构造Vue实例之后,就不会起作用了:

    var obj={
        a: 1
    };
   var app = new Vue({
       el: "#app",
       data:obj,
   });
    Object.freeze(obj);
    console.log(app.a);//1
    obj.a=2;
    console.log(app.a);//2

这个的原因是什么,我还没有搞清楚,如果有哪位大神可以指导一下,非常感谢!

参考:
1.Vue.js官方文档
2.《Vue.js实战》

猜你喜欢

转载自blog.csdn.net/weixin_42695446/article/details/84617456