Vue 注意事项 模板语法 单双向绑定 语法格式 MVVM框架 Object.defineProperty和数据代理操作

Posted IT_Holmes

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Vue 注意事项 模板语法 单双向绑定 语法格式 MVVM框架 Object.defineProperty和数据代理操作相关的知识,希望对你有一定的参考价值。

1.Vue 注意事项

1. 容器 和 实例

这里牢记一点:

多个容器对应一个实例,多个实例对应一个容器都是错误的!!!
容器和Vue实例必须是一一对应的关系,不能混杂。

2. 区分好js代码 和 js表达式

就算在Vue实例中,没有表现特定属性或方法,在一些js表达式也是可以使用的。如下:{{Date.now()}} 。

在这里插入图片描述
解释一下js表达式和js代码区别:

js代码直接定义了走向什么的,例如:if,for等等语句。
js表达式,一个表达式会产生一个值,例如:a+b,a,三元表达式,函数表达式(上面的Date.now(),就是一个函数调用表达式)等,都是js表达式。

3. 真是开发中只有一个Vue实例

真是开发中只有一个Vue实例,并且配合一些组件。

4. {{xxx}} 中要写js代码或js表达式

{{xxx}} 中的xxx要写js表达式,且xxx会自动读取到data中的所有属性。

此外,就是要尽量使用开发版本的Vue,生产版本的Vue错误提示不会很明显。

2. Vue 模板语法

2.1 {{xxx}} 插值语法

就是{{xxx}},这种语法就是插值语法。

2.2 v-??? 指令语法

指令语法功能:
用于解析标签,包括:标签属性、标签体内容、绑定时间等等,下面的v-bind(对标签属性)只是一个例子。

v-bind能够将所对应的属性中的引号里面的值,当成js表达式来执行。此外,v-bind可以给任何一个属性标签来动态绑定,大多数用在href上面。

v-bind:href=“xxx” 或 简写为 :href=“xxx” ,当然这里的xxx只能写js表达式。

源码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
</head>
<body>
    <div id="root">
        <!-- 差值语法显示 -->
        <h1>差值语法</h1>
        <h3>你好,{{name}}</h3>
        <hr>
        <!-- 指令语法显示 -->
        <h1>指令语法</h1>
        <!-- v-bind可以将引号中url当成表达式来执行,而不是字符串。 -->
        <a v-bind:href="school.url.toUpperCase()">百度1</a>
        <a :href="school.url">百度2</a>
    </div>
    <script>
        Vue.config.productionTip = false;
        new Vue({
            el:"#root",
            data:{
                name:"张三",
                school:{
                    url:"http://www.baidu.com",
                    name:"李四"
                }
                
            }
        });
    </script>
</body>
</html>

提示:
Vue中有很多的指令,且形式都是v-???,这里的v就是Vue,v-bind只是其中的一员,指令语法还有很多的。当然指令语法也可以使用其他js表达式,如上面的toUpperCase()。

像这种镶嵌格式的,就像下图表示:
在这里插入图片描述

3. 单向绑定和双向绑定

v-bind是单向绑定,v-model是双向绑定。这里的绑定是和Vue开发者工具里的data来绑定的。

注意:

v-model只能应用在表单元素(输入元素)上 ,简而言之就是要有value值。
Vue的两种绑定方式总结:

在这里插入图片描述

Vue的两种绑定方式的简写:

1. v-bind: 可以简写为: 。
2. v-model:value = "xxx"可以简写为v-model = “xxx” 。

在这里插入图片描述

在这里插入图片描述
源码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
</head>
<body>
    <div id="root">
        <!-- v-bind是单项绑定 -->
        单项数据绑定:<input type="text" v-bind:value="name">
        单项数据绑定:<input type="text" :value="name">
        <br>
        <!-- v-model是双向绑定 -->
        双项数据绑定:<input type="text" v-model:value="name">
		 双项数据绑定:<input type="text" v-model="name">
        <!-- 如下代码时错误的,因为v-model只能应用在表单元素(输入元素)上 ,简而言之就是要有value值。-->
        <h1 v-medolx="111">你好啊</h1>
    </div>

    <script>
        Vue.config.productionTip = false;
        const vm = new Vue({
            el:"#root",
            data:{
                name:"张三"
            }
        });
    </script>
</body>
</html>

4. el和data的两种写法方式

4.1 介绍 Vue实例对象一些方法

这里我们打印一个Vue的实例,来看看里面的内容,见图。
在这里插入图片描述
在这里插入图片描述

4.2 el的两种写法方式

第一种是直接用el来定义,第二种是$mount()方法来实现。见源码。

源码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
</head>
<body>
    <div id="root">
        <h1>{{name}}</h1>
    </div>
    <script>
        Vue.config.productionTip = false;
        const vm = new Vue({
            // el:'',
            data:{
                name:"张三"
            }
        })
        console.log(vm);
        //$mount比el:'xxx'更加灵活一些,就像下面延迟两秒一样。
        setTimeout(()=>{
            vm.$mount('#root');//$mount可以代表el:'xxx'来操作。
        },2000);
    </script>
</body>
</html>

4.3 data 两种写法方式

data的两种写法:第一种是对象式,第二种是函数式。
注意函数式,非常重要,组件必须用到函数式,此外data函数可以简化,并且这里不能使用箭头函数,因为这里的this指向必须是Vue实例对象!

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
</head>
<body>
    <div id="root">
        <h1>{{name}}</h1>
    </div>
    <script>
        Vue.config.productionTip = false;
        const vm = new Vue({
            el:'#root',
            // data的第一种写法:对象式
            // data:{
            //     name:"张三"
            // }

            // data的第二种写法:函数式 ,学习组件很重要!!
            /*
            data:function(){
                console.log(this);
                return{
                    name:"张三"
                }
            }
            */

            // 可以简化上面的写法为:
            data(){
                console.log(this); //这里的this指向Vue实例对象,因为以后要用到Vue实例对象,所以不能使用箭头函数,否则指向window全局。
                return {
                    name:"张三"
                }
            }
        })

    </script>
</body>
</html>

5. 了解Vue的MVVM架构

DOM Listeners :模块监听。

Data Bindings : 数据绑定。

这俩个都是很重要的存在记住!
在这里插入图片描述
通过上图,可以了解到MVVM整体的架构。

注意:

1. data中所有的属性,最后都出现在了vm实例对象上面。
2. vm升上所有的属性和Vue原型上所有的属性,都可以直接在Vue模板中使用。
见源码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
</head>
<body>
    <div id="root">
        <h1>学校名称:{{name}}</h1>
        <h1>学校地址:{{address}}</h1>
        <h1>1+1 为什么等于 {{1+1}} ?</h1>
        <h1>测试Vue的$options,{{$options}}</h1>    <!--查看测试Vue的$option内置函数 -->
        <h1>测试Vue原型$emit,{{$emit}}</h1>         <!--查看测试Vue的$emit原型函数 -->
        <h1>测试没有$开头的 _c,{{_c}}</h1>          <!--查看测试Vue的 _C 函数 -->
    </div>
    <script>
        Vue.config.productionTip = false;
        const vm = new Vue({
            // el:'#root',
            //data中的内容,会传送到vm身上。
            data:{
                name:"清华大学",
                address:"北京"
            }
        })
        vm.$mount("#root");
        console.log(vm);
    </script>
</body>
</html>

6. Object.defineProperty 常用方法

6.1 功能 给对象添加属性

Object.defineProperty(对象名 , ’ 属性名 ’ , { value=’ 属性值 ’ }) , 可以给对象添加属性。

<script>
    let person = {
        name:"张三",
        sex:"男"
    }
    Object.defineProperty(person,'age',{
        value:"18"
    })
    console.log(person);
</script>

6.2 如何设置能否被枚举遍历

通过Object.defineProperty增加的属性,是不可以被枚举的,也就是不能被遍历。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <script>
        let person = {
            name:"张三",
            sex:"男"
        }
        //这里的age,设置出来是不可以枚举的,也就是不可以被遍历出来的
        Object.defineProperty(person,'age',{
            value:"18"
        });

        console.log("----------");
        console.log(person);

        console.log("----------");
        //Object.keys(person) ,可以打印person中的键名
        console.log(Object.keys(person));

        console.log("----------");
        //for ... in 遍历来遍历键值。
        for(let v in person){
            console.log(person[v]);
        }

        
    </script>
</body>
</html>

此外,ObjectdefineProperty增加的属性,在打印出来后,有些不一样,颜色会比其他直接定义的属性浅一些。

在这里插入图片描述
如果想要在defineProperty增加的属性里,想让他枚举的话,可以在属性值中定义enumerable为true。其中enumerable含义是,可列举的。这样设置完后,age的颜色就一样了。

    //这里的设置了enumerable为true,就可以来进行遍历age了。
    Object.defineProperty(person,'age',{
        value:"18",
        enumerable:true //这里默认值为false
    });

在这里插入图片描述

6.3 如何定义属性值能否改变

此外,ObjectdefineProperty定义的属性值是没法改变的。

在这里插入图片描述
同样,将writable设置为true,就能修改属性值了。

    Object.defineProperty(person,'age',{
        value:"18",
        enumerable:true, //设置能否枚举遍历。
        writable:true,  //设置能否修改属性值。
    });

在这里插入图片描述

6.4 如何定义属性能否被删除

我们先看看,在使用ObjectdefineProperty,没有设置删除的属性下,是属性被删除的不可以的。

在这里插入图片描述
如何设置,这里就用到了configurable来设置。

    Object.defineProperty(person,'age',{
        value:"18",
        enumerable:true, //设置能否枚举遍历。
        writable:true,  //设置能否修改属性值。
        configurable:true //设置能否进行删除属性操作。
    });

在这里插入图片描述

7. Object.defineProperty 高级方法

7.1 getter 方法 (谁获得,就调用getter方法)

7.1.1 getter 函数方法执行过程

比较高级的做法,就是使用get函数(getter)来操作

下面代码,通过number就可以控制person中的age值了,如果直接将age:number写在person中,那就实现不了number操控age的值。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <script>
        let number = 18; //通过number就可以控制person中的age值了,如果直接将age:number写在person中,那就实现不了number操控age的值。
        let person = {
            name:"zhangsan",
            sex:"男"
        }
        
        //比较高级的做法,就是使用get函数(getter)来操作
        Object.defineProperty(person,'age',{
            //当有人读取perso的age属性时,get函数就会被调用,且返回值就是age的值。
            get:function(){
                console.log("有人读取age属性了");
                return number;
            }
        });
        console.log(person);
    </script>
</body>
</html>

在这里插入图片描述
在这里插入图片描述

7.1.2 getter 函数方法的三种写法形式

见源码:

<script>
    let number = 18; //通过number就可以控制person中的age值了,如果直接将age:number写在person中,那就实现不了number操控age的值。
    let person = {
        name:"zhangsan",
        sex:"男"
    }
    
    //比较高级的做法,就是使用get函数(getter)来操作
    Object.defineProperty(person,'age',{
        //当有人读取perso的age属性时,get函数就会被调用,且返回值就是age的值。

        // 函数的写法看下面3中:
        /*
        //第一种,不写名字
        get:function(){
            console.log("有人读取age属性了");
            return number;
        }*/

        /*
        //第二种,有名字
        get:function name(){
            console.log("有人读取age属性了");
            return number;
        }*/

        //第三种,简化(正常都是简化)
        get(){
            console.log("有人读取age属性了");
            return number;
        }
    });
    console.log(person);
</script>

7.2 setter 函数方法 (谁设置,就调用setter方法)

setter方法和getter方法一样,就是调用时的执行条件不同,三种写法也一样。

<script>
    let number = 18; //通过number就可以控制person中的age值了,如果直接将age:number写在person中,那就实现不了number操控age的值。
    let person = {
        name:"zhangsan",
        sex:"男"
    }
    
    //比较高级的做法,就是使用get函数(getter)来操作
    Object.defineProperty(person,'age',{
        //当有人读取perso的age属性时,get函数就会被调用,且返回值就是age的值。
        get(){
            console.log("有人读取age属性了");
            return number;
        },
        set(value){
            console.log("有人修改了age属性");
            number = value; //这里设置number值,为value,就可以修改number来显示age了。
        }
    });
    console.log(person);
</script>

在这里插入图片描述

8. 数据代理

8.1 数据代理定义

数据代理就是通过一个对象代理对另一个对象的属性进行操作。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <script>
        let obj1 = {x:100};
        let obj2 = {y:200};

        //数据代理就是通过一个对象代理对另一个对象的属性进行操作。
        Object.defineProperty(obj2,'x',{
            get(){
                return obj1.x;
            },
            set(value){
                obj1.x = value;
                console.log("修改成功")
            }
        })
    </script>
</body>
</html>

8.2 数据代理延伸

其实我们打印一个vm对象,看到我们在data中定义的数据,是因为Object.defineProperty中的setter和getter来得到的。

在这里插入图片描述

vm中的data,就是存在了vm实例对象本身,但在控制台端输入vm._data,得到的结果就是这里的data属性。

<script>
    Vue.config.productionTip = false;
    const vm = new Vue({
        // el:'#root',
        //这里的data存在了vm实例对象本身,但在控制台端输入vm._data,得到的结果就是这里的data属性。
        data:{
            name:"清华大学",
            address:"北京"
        }

    });
    vm.$mount("#root");
    console.log(vm)

;
在这里插入图片描述

我们可以通过这种方式来参考和解决相关问题。见下图:

在这里插入图片描述
所以本质上数据代理,就是通过setter和getter,修改data中的内容,进而修改了浏览器前端的内容。
在这里插入图片描述
对于数据代理,就是这样子的其中的Vue实例对象中的 name: 和 address: 就是通过Object.defineProperty的getter和setter,从_data中获得绑定的。

在这里插入图片描述
此外,注意这里的_data里的内容不是数据代理,而是数据劫持。
在这里插入图片描述

以上是关于Vue 注意事项 模板语法 单双向绑定 语法格式 MVVM框架 Object.defineProperty和数据代理操作的主要内容,如果未能解决你的问题,请参考以下文章

Vue模板语法——事件绑定

Vue模板语法

typescript 模板语法:双向绑定

Vue模板语法

Vue双向数据绑定

Vue基础入门讲义-语法基础