当前位置: 首页 > news >正文

VUE2 学习笔记2 数据绑定、数据代理、MVVM

目录

模版语法v-bind

数据绑定

MVVM模型

数据代理

简介Object.defineProperty

什么是数据代理

Vue中的数据代理


模版语法v-bind

模版语法:指的是Vue模板中的VUE语法。笔记1里有记录过插值语法

还有一类模板语法是指令语法

对于标签中某个属性的值,如果想把该值设定为data中的数据,使用插值语法是无法生效的(以前是有这种语法,但现在已经被移除了),可以使用v-bind:属性="变量名"的语法,v-bind:可以简写成:。

    <div id="root"><a v-bind:href="url">1</a><a :href="url">2</a></div><script type="text/javascript" src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script><script>new Vue({el: '#root',data:{url: 'xxx',}})</script>

当使用v-bind:或:简写形式时,解析器会把value值当做Js表达式解析(可以是变量,也可以是js语句)。也就是:href="url"的"url"部分。

v-bind为js语句:

    <div id="root"><a v-bind:href="url">1</a><a :href="url.toUpperCase()">2</a></div>

如果v-bind绑定的数据,在data中没有定义:

会报错误,提示property or method '变量名' is not defined on the instance but referenced during render。

什么时候用插值语法,什么时候用指令语法:对于标签体的内容,也就是两个标签<></>中间夹的内容,应该使用插值语法。指令语法用于标签属性。

插值语法:用于解析标签体的内容。指令语法:用于解析标签(指令语法写在标签属性中,可以给标签添加属性、事件、标签体等)。

数据绑定

对于一个属性,其值和一个数据绑定,这种现象就是数据绑定。

对于v-bind来说,它是实现数据绑定的一种方式。

数据绑定分为单向数据绑定双向数据绑定

单向数据绑定:属性和数据绑定,当后台的数据变化时,页面当中的属性值也会发生变化。当页面当中的属性值改变后,后台的数据不会发生改变。

    <div id="root"><input :value="inputData"></div><script type="text/javascript" src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script><script>new Vue({el: '#root',data:{inputData: 'catcat',}})</script>

刚打开页面,input框中的数据是catcat。

v-bind就是单向数据绑定。后台数据的变化会反应到页面上,页面数据的变化不会反应到后台。

当把页面上的内容修改为dogdog之后,后台的值还是catcat

双向数据绑定:后台数据的改变可以反应在页面上,页面上数据变化时,也可以反应在后台。另一个指令v-model是双向数据绑定

    <div id="root"><input :value="inputData"><input v-model:value="modelData"></div><script type="text/javascript" src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script><script>let vm = new Vue({el: '#root',data: {inputData: 'catcat',modelData: 'dogdog',}})</script>

当把页面中的值改为dogdogyeah后,后台的值也会发生变化。

但并不是所有标签中v-model都能使用。v-model一般应用在表单类/输入类元素上,这类元素都有一个value值。v-model:value=''可以简写成v-model:'',因为v-model默认绑定的就是value值。

    <div id="root"><input :value="inputData"><input v-model="modelData"></div>

MVVM模型

Vue的设计收到了MVVM模型的启发,Vue没有完全遵循MVVM模型,但大体上参考了这个模型。

MVVM的分隔方式是M、V、VM。

其中M是Model,模型,对应Vue实例data中的数据。

V是View,对应Vue模版。

VM是视图模型ViewModel,是对应Vue实例对象。

因为new Vue充当ViewModel,所以其返回的实例值一般命名为vm,但其实这个值也可以自己随便写,就是vm更加合理一点。

data中的数据,最后会体现在vm上。

插值语法可以使用所有在vm、vm原型链上的属性和方法。且实例vm已经内置在{{}}里,因此在{{}}里不需要写this或者vm。直接写属性和方法就可以。实际上,vm、vm原型链上所有的属性和方法都可以在Vue模版中使用

数据代理

数据代理使用Object.defineProperty方法,数据劫持、计算属性等也使用了这个方法。

Object.defineProperty用于给一个对象添加属性。Object.defineProperty接收三个属性,分别是(要添加属性的对象,要添加的属性名称,配置项)

简介Object.defineProperty

        let demo = {name:'catcat',age:18,}Object.defineProperty(demo, 'color', {value: 'orange',});console.log(demo);

Object.defineProperty设置的属性,和用demo{color:'orange'}直接赋值是不一样的,用defineProperty加入的属性默认是不可枚举的,也就是不能够被遍历的。

        Object.defineProperty(demo, 'color', {value: 'orange',});console.log(Object.keys(demo));for(let key in demo){console.log(demo[key]);}

只能遍历到name和age,遍历不到color。

如果希望defineProperty新加的属性也能被遍历,需要设置enumerable:true(enumerable设置属性值是否可以被枚举,默认为false)。

        Object.defineProperty(demo, 'color', {value: 'orange',enumerable:true,});

用Object.defineProperty新加的属性默认是无法修改的。设置demo.color = 'blue'不会生效。如果希望属性可以被修改,需要设置writable:true。writable设置属性是否可以被修改,默认为false。

        Object.defineProperty(demo, 'color', {value: 'orange',enumerable:true,writable:true,});

用Object.defineProperty新加的属性默认不可删除。写delete demo.color,color不会被删除。需要设置configurable:true,属性才能被删除。configurable控制属性是否可以被删除,默认为false。

        Object.defineProperty(demo, 'color', {value: 'orange',enumerable:true,writable:true,configurable:true,});

与直接在对象字面量上赋值不同,字面量上的赋值可以删除,可以修改,可以任意进行操作。而defineProperty可以设置配置项,可以对追加的属性进行很多配置。

设置get

可以用defineProperty在新加的属性上设置get。get在读取属性时触发。

考虑下面这种情况:

        let color = 'orange';let demo = {name:'catcat',age:18,color: color,};

当变量color发生变化时,demo.color不会跟着变化。只有在初始赋值时会把color值赋给demo.color,赋值完两者之间就没有关系了,因此即使过后改变变量color,不会影响demo.color。

但是这种效果可以用defineProperty实现,设置get,当读取demo.color时,返回color值即可。get是函数名,get有一个函数体,一般把get和函数体统称为getter。

        let color = 'orange';let demo = {name:'catcat',age:18,};Object.defineProperty(demo,'color',{get(){return color;}});

设置set

可以用defineProperty在新加的属性上设置set。set在给属性赋值时触发。

不管是设置get还是set,要注意不要直接访问当前设置的这个属性,否则会导致无限回调。

可以通过另一个变量辅助进行set和get。

        let demo = {name:'catcat',age:18,};Object.defineProperty(demo,'color',{get(){return this._color;},set(value){this._color = value + 'color';}});

什么是数据代理

数据代理是通过一个对象,代理另一个对象中属性的操作。

比如我有一个对象Obj,他有属性x,我访问x,使用Obj.x访问就可以了。但如果还有另一个对象Obj2,Obj2也想访问x,也想修改x,则可以使用代理。通过Obj2代理对Obj1中属性的操作。也就是说,虽然Obj2中没有相关的属性和方法,但是可以通过Obj2代理对Obj1的操作。

        let obj1 = {x : 100,}let obj2 = {};Object.defineProperty(obj2, 'x',{get(){return obj1.x;},set(value){obj1.x = value;},})

这里给obj2也添加属性x,但当访问obj2的x时,返回的是obj的x。修改obj2的x时,修改的是obj1的x。实现了对obj1的代理。

以上是一个非常简单的数据代理的例子。

Vue中的数据代理

Vue实例身上的data数据就是通过数据代理进行的。

    <div id="root"><h1>姓名:{{name}}</h1><h1>年龄:{{age}}</h1></div><script type="text/javascript" src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script><script>    let vm =  new Vue({el: '#root',data(){return{name:'catcat',age:14,}}})</script>

对于上面这段代码,Vue实例vm中,有在data中配置的name和age,对实例vm身上的name和age进行读写操作,实际上就是用的数据代理,name和age有自己的getter和setter。

如果读取vm上的name值,实际上会触发name的getter,这个getter会返回data.name。

如果通过vm去修改name,实际上会触发name的setter,这个setter会修改data.name。

其实是一个数据代理。

data对象只是new Vue里的一个配置,并不是全局变量,vm是如何访问data:

vm把data存在自己身上的某个属性。

这个属性是_data。

        let data = {name: 'catcat',age: 14,}let vm = new Vue({el: '#root',data,})

实际上vm的_data就是在new Vue配置对象里配置的data,这个data值是配置的data值,vm._data=options.data,options.data = data。修改vm._data,配置的data也会改变。

为什么需要用数据代理访问data:通过数据代理,把data上的数据放在vm上一份,在访问data中的数据时,不需要写_data,直接写属性就可以了。更方便开发。

数据代理的原理:通过Object.defineProperty把data对象中的所有属性添加到vm上。

为每一个vm上的属性都设置getter和setter,通过getter和setter去操作data。

_data中的数据并不是单纯复制data,_data为了实现响应式,应用了数据劫持。数据劫持之后会介绍。数据劫持,其实就是当_data中的数据改变时,data中的数据也相应改变,这可能会导致页面中的数据也改变,就需要有一个监听机制,监听data是否发生改变,并更新页面上的值。这个机制就是数据劫持。

http://www.xdnf.cn/news/1156555.html

相关文章:

  • 【数据结构】第一讲 —— 概论
  • 基于Arduino的智能寻迹小车设计
  • 剑指offer——链表:旋转数组的最小数字
  • 【OD机试】池化资源共享
  • 「Java案例」利用方法求反素数
  • Ubuntu挂载和取消挂载
  • LP-MSPM0G3507学习--07定时器之二定时节拍
  • ZYNQ平台深度剖析:EMMC/FLASH/SD卡性能测试与创新实践
  • 从磁记录到数据中心:磁盘原理与服务器架构的完整技术链路
  • 两个数据表的故事:第 1 部分
  • Spring之事务使用指南
  • Java行为型模式---解释器模式
  • Openlayers 面试题及答案180道(121-140)
  • Node.js Express keep-alive 超时时间设置
  • @import导入css样式、scss变量用法、static目录
  • Java中List<int[]>()和List<int[]>[]的区别
  • PAT 1049 Counting Ones
  • 医学图像超分辨率重建深度学习模型开发报告
  • 如何用immich将苹果手机中的照片备份到指定文件夹
  • Word for mac使用宏
  • UniApp 常用UI库
  • 机器视觉---深度图像存储格式
  • 闲庭信步使用图像验证平台加速FPGA的开发:第二十五课——正弦波图像的FPGA实现
  • 数据存储方案h5py
  • 【C++基础】面试高频考点解析:extern “C“ 的链接陷阱与真题实战
  • MySQL详解三
  • MyBatis Plus高效开发指南
  • 第459场周赛
  • ESXi6.7硬件传感器红色警示信息
  • 详解Mysql解决深分页方案