Vue2.(Vue的指令和数据代理原理,数据监测)

目录

vue 的两个特性

数据驱动视图:

双向数据绑定:

3.vue的基本使用

vue 指令

1. 内容渲染指令(v-text,{{ }},v-html)

2. 属性绑定指令(v-bind:,简写 :)

绑定样式

2.1. class样式写法:

 2.2. style样式

3.事件绑定指令(v-on:,简写 @)

3.1事件对象$event

3.2事件修饰符:

3.3按键修饰符:(@keyup.esc,@keyup.enter)

4.双向绑定指令(v-model)

4.1v-model的修饰符(.number,.trim,.lazy)

5.条件渲染指令(v-if,v-else,v-else,v-show,)

5.1.v-if 和v-show 的区别

6.列表(循环)渲染指令(v-for)

6.1key 的注意事项

6.2 label的for属性

6.3key的内部原理

7.v-cloak指令(防止闪现, 与 css 配合: [v-cloak] { display: none })

8.v-once指令(初次动态渲染后不再改变)

9.v-pre指令(被该指令用的vue不会去解析它)

列表案例

Vue中的数据代理

1.Object.defineProperty方法

2.数据代理:通过一个对象代理对另一个对象中属性的操作

3.Vue的数据代理

Vue的数据监测

1. vue会监视data中所有层次的数据。

2. 如何监测对象中的数据?

 3. 如何监测数组中的数据?

 4.在Vue修改数组中的某个元素一定要用如下方法:


vue 的两个特性

  1. 数据驱动视图:

    • 数据的变化会驱动视图自动更新

    • 好处:程序员只管把数据维护好,那么页面结构会被 vue 自动渲染出来!

  2. 双向数据绑定:

    在网页中,form 表单负责采集数据,Ajax 负责提交数据

    • js 数据的变化,会被自动渲染到页面上

    • 页面上表单采集的数据发生变化的时候,会被 vue 自动获取到,并更新到 js 数据中

注意:数据驱动视图和双向数据绑定的底层原理是 MVVM(Mode 数据源、View 视图、ViewModel 就是 vue 的实例)

ViewModel 作为 MVVM 的核心 ,是它把当前页面的 数据源 Model )和 页面的结构 View )连接在了一起。
数据源发生变化 时,会被 ViewModel 监听到, VM 会根据最新的数据源 自动更新 页面的结构
表单元素的值发生变化 时,也会被 VM 监听到, VM 会把变化过后最新的值 自动同步 Model 数据源中

3.vue的基本使用

  • ①导入vue.js script 脚本文件
  • ②在页面中声明一个将要被vue 所控制的DOM 区域
  • ③创建vm 实例对象(vue 实例对象)
<body>
        <!-- 希望Vue能够控制下面的div,
        帮我们在把数据填充到div内部 -->
    <div id="app">{{username}}</div>

    <!-- 1.导入Vue的库文件,在window全局
        就有这个Vue这个构造函数 -->
    <script src="./lib/vue-2.6.12.js"></script>
    <!-- 2.创建Vue的实例对象 -->
    <script>
        //创建Vue的实例对象
        const vm = new Vue({
            /* el属性是固定写法,表示当前vm实例
            要控制页面哪个区域,接收的值是一个选择器 */
            el: '#app',
            // data对象就是要渲染到页面的数据
            data: {
                username: 'dilireba'
            }
        })
    </script>
</body>

vue 指令

1. 内容渲染指令(v-text,{{ }},v-html)

  1. v-text 指令的缺点:会覆盖元素内部原有的内容!

  2. {{ }} 插值表达式:在实际开发中用的最多,只是内容的占位符,不会覆盖原有的内容!

  3. v-html 指令的作用:可以把带有标签的字符串,渲染成真正的 HTML 内容!

    <div id="app">
        <!-- 内容渲染指令 -->
        <!-- v-text指令的缺点,会覆盖元素
            内部原有的内容!  -->
        <p v-text="username"></p>
        <p v-text="gender">性别:</p>

        <hr>
        <!-- 解决方法:弥补v-text的缺点:插值表达式{{}} -->
        <!-- {{}}插值表达式,实际开发运用最多 -->
        <p>姓名:{{username}}</p>
        <p>性别:{{gender}}</p>

        <hr>
        <!-- {{}}和v-text只能渲染纯文本内容,
            不能渲染html内容 -->
        <div v-text="info"></div>
        <div>{{info}}</div>

        <!-- 需要用v-html渲染带标签的字符串 -->
        <div v-html="info"></div>
    </div>

    <script src="./lib/vue-2.6.12.js"></script>
    <script>
        var vm = new Vue({
            el: '#app',
            data: {
                username: 'dilireba',
                gender: '女',
info: '<h4 style="color:red;font-weight:bold;">Hello Vue!</h4>'
            }
        })
    </script>

2. 属性绑定指令(v-bind:,简写 :)

注意:插值表达式只能用在元素的内容节点中,不能用在元素的属性节点中!

  • 在 vue 中,可以使用 v-bind: 指令,为元素的属性动态绑定值;

  • 简写是英文的 :

  • 在使用 v-bind 属性绑定期间,如果绑定内容需要进行动态拼接,则字符串的外面应该包裹单引号,例如:

    <div :title="'box' + index">这是一个 div</div>
    <div id="app">
        <!-- 属性绑定指令 -->
        <!-- 插值表达式只能用到内容节点元素中,
          不能应用到属性节点上 -->
        <!--把tips值放到属性placeholder里面,需
          要用的v-bind -->
        <input type="text" v-bind:placeholder="tips">
        <hr>
        <!-- Vue规定v-bind:指令可以简写为: -->
        <img :src="photo" alt="" style="width: 150px;">

        <hr>
        <!-- 在 vue 提供的模板渲染语法中,除了
          支持绑定简单的数据值之外,还支持 Javascript 表达式的运算 -->
        <div>1+2的结果是:{{1+2}}</div>
 <div>{{ tips }}反转后的结果是:{{ tips.split('').reverse().join('')}}</div>

        <!-- 在使用 v-bind 属性绑定期间,如果绑
          定内容需要进行动态拼接,则字符串的外面应该
        包裹单引号,双引号里面的内容看成js代码 -->
        <div :title="'box'+index">这是一个div</div>
    </div>

    <script src="./lib/vue-2.6.12.js"></script>
    <script>
        var vm = new Vue({
            el: '#app',
            data: {
                tips: '请输入用户名',
                photo: 'https://cn.vuejs.org/images/logo.svg',
                index: 3
            }
        })
    </script>

绑定样式

2.1. class样式写法:

  • class="xxx" xxx可以是字符串、对象、数组。

  • 字符串写法适用于:类名不确定,要动态获取。

  • 对象写法适用于:要绑定多个样式,个数不确定,名字也不确定。
  • 数组写法适用于:要绑定多个样式,个数确定,名字也确定,但不确定用不用。

 2.2. style样式

                :style="{fontSize: xxx}"其中xxx是动态值。

                :style="[a,b]"其中a、b是样式对象。

	data:{
				name:'迪丽热巴',
				mood:'normal',
				classArr:['atguigu1','atguigu2','atguigu3'],
				classObj:{
					atguigu1:false,
					atguigu2:false,
				},
				styleObj:{
					fontSize: '40px',
					color:'red',
				},
				styleObj2:{
					backgroundColor:'orange'
				},
				styleArr:[
					{
						fontSize: '40px',
						color:'blue',
					},
					{
						backgroundColor:'gray'
					}
				]
			},

3.事件绑定指令(v-on:,简写 @)

  1. v-on: 简写是 @

  2. 语法格式为:

<button @click="add"></button>

methods: {
   add() {
            // 如果在方法中要修改 data 中的数据,
            //可以通过 this 访问到
            this.count += 1
   }
}

    <div id="app">
        <!-- 事件绑定指令 -->
        <p>count 的值是:{{count}}</p>
        <!-- v-on语法,v-on:事件名称="事件处理函数名称" -->
        <!-- 在绑定事件处理函数的时候可以使用()进行传递参数 -->
        <!-- v-on:指令可以被简写为@ -->
        <button v-on:click="add(1)">+1</button>
        <button @click="sub">-1</button>
    </div>


    <script src="./lib/vue-2.6.12.js"></script>
    <script>
        var vm = new Vue({
            el: '#app',
            data: {
                count: 0,
            },
            /*methods的作用,就是定义事件的处理函数  */
            methods: {
                /* add: function() {
                    console.log('ok');
                } */
                /* es6语法简写 */
                add(n) {
                    console.log(vm === this);
                    /*  vm.count += 1 */
                    this.count += n
                },
                sub() {
                    console.log('no');
                    this.count -= 1
                }
            }
        })
    </script>

3.1事件对象$event

$event 的应用场景:如果默认的事件对象 e 被覆盖了,则可以手动传递一个 $event。例如:

<button @click="add(3, $event)"></button>

methods: {
   add(n, e) {
            // 如果在方法中要修改 data 中的数据,可以通过 this 访问到
            this.count += 1
   }
}

    <div id="app">
        <p>count的值是:{{count}}</p>
        <!-- 如果count是偶数,则 按钮背景变成红色,否则取消背景颜色 -->
        <!-- vue提供了内置变量,名字叫做$event,它就是原生DOM的事件对象e -->
        <button @click="add($event,1)">+N</button>
    </div>
    <script src="./lib/vue-2.6.12.js"></script>
    <script>
        var vm = new Vue({
            el: '#app',
            data: {
                count: 0,
            },
            methods: {
                add(e, n) {
                    this.count += n
                    console.log(e);

                    //判断this.count的值是否为偶数
                    if (this.count % 2 === 0) {
                        //偶数
                        e.target.style.backgroundColor = 'red'
                    } else {
                        //奇数
                        e.target.style.backgroundColor = ''
                    }
                }
            }
        })
    </script>

3.2事件修饰符:

  • .prevent

    <a @click.prevent="xxx">链接</a>
  • .stop

    <button @click.stop="xxx">按钮</button>
    <div id="app">
        <!-- 事件修饰符,绑定在事件绑定后面,
        如event.preventDefault()阻止事件默认行为
        或event.stopPropagation()阻止事件冒泡,简化成.prevent和.stop -->
 <a href="http://www.baidu.com" @click.prevent="show">跳转到百度页面</a>

        <hr>
<div style="height: 200px;background-color: orange;padding-left: 100px;line-height: 200px;" @click="divHandler">
      <button @click.stop="btnHandler">按钮</button>
        </div>
    </div>
    <script src="./lib/vue-2.6.12.js"></script>
    <script>
        var vm = new Vue({
            el: '#app',
            data: {

            },
            methods: {
                show() {
                    /* e.preventDefault(); */
                    console.log('点击了a链接');
                },
                btnHandler() {

                    console.log('btnHandler');
                },
                divHandler() {
                    console.log('divHandler');
                },

            }
        })
    </script>

3.3按键修饰符:(@keyup.esc,@keyup.enter)

    <!-- 按键修饰符 -->
    <div id="app">
        <input type="text" @keyup.esc="clearInput" @keyup.enter="commitAjax">
    </div>
    <script src="./lib/vue-2.6.12.js"></script>
    <script>
        const vm = new Vue({
            el: '#app',
            data: {},
            methods: {
                clearInput(e) {
                    console.log('触发了clearInput方法');
                    e.target.value = ''
                },
                commitAjax() {
                    console.log('触发了commitAjax方法');
                }
            },
        })
    </script>

4.双向绑定指令(v-model)

vue 提供了 v-model 双向数据绑定 指令,用来辅助开发者在 不操作 DOM 的前提下, 快速获取表单的数据
    <!-- 双向绑定指令v-model指令,用在表单元素input输入框,textare,select下拉菜单 -->
    <div id="app">
        <p>用户的名字是:{{username}}</p>
        <input type="text" v-model="username">
        <hr>
        <input type="text" :value="username">
        <hr>
        <select v-model="city">
          <option value="">请选择城市</option>
          <option value="1">北京</option>
          <option value="2">上海</option>
          <option value="3">广州</option>
        </select>
    </div>
    <script src="./lib/vue-2.6.12.js"></script>
    <script>
        const vm = new Vue({
            el: '#app',
            data: {
                username: 'dilireba',
                city: '2'
            }
        })
    </script>

4.1v-model的修饰符(.number,.trim,.lazy)

    <!-- v-model的修饰符 -->
    <div id="app">
        <!-- 1.v-model的修饰符将用户输入的字符串转为数值类型
      .number -->
        <input type="text" v-model.number="n1">+<input type="text" v-model.number="n2">=<span>{{n1+n2}}</span>
        <hr>
        <!--2. 修饰符.trim去除两端空格 -->
        <input type="text" v-model.trim="username">
        <button @click="showName">获取用户名</button>
        <hr>
        <!-- 3.修饰符.lazy 在‘change’时而非“input”时更新 -->
        <input type="text" v-model.lazy="username">
    </div>
    <script src="./lib/vue-2.6.12.js"></script>
    <script>
        const vm = new Vue({
            el: '#app',
            data: {
                username: 'dilireba',
                n1: 1,
                n2: 2,
            },
            methods: {
                showName() {
                    console.log(`用户名是:"${this.username}"`)
                }
            }
        })
    </script>

5.条件渲染指令(v-if,v-else,v-else,v-show,

条件渲染指令用来辅助开发者按需控制DOM 的显示与隐藏。条件渲染指令有如下两个,分别是:
  • v-if
  • v-show

5.1.v-if v-show 的区别

实现原理不同:
  • v-if 指令会动态地创建或移除DOM 元素,从而控制元素在页面上的显示与隐藏;
  • v-show 指令会动态为元素添加或移除style="display: none;" 样式,从而控制元素的显示与隐藏;
性能消耗不同:
v-if有更高的切换开销,而v-show有更高的初始渲染开销。因此:
  • 如果需要非常频繁地切换,则使用v-show 较好
  • 如果在运行时条件很少改变,则使用v-if 较好
    <!-- 条件渲染指令用来辅助开发者按需控制DOM 的显示与隐藏,v-if和v-show -->
    <div id="app">

        <!-- `v-if` 的原理是:每次动态创建或移除元素,实现元素的显示和隐藏.
        应用场景:如果刚进入页面的时候,某些元素默认不需要被展示,而且后期这个元素很可能也不需要被展示出来,此时 v-if 性能更好。-->
        <p v-if="flag">这是被v-if控制的元素</p>

        <!--v-show 的原理是:动态为元素添加或移除 display: none 样式,来实现元素的显示和隐藏
          应用场景:如果要频繁的切换元素的显示状态,用 v-show 性能会更好 -->
        <p v-show="flag">这是被v-show控制的元素</p>

        <hr>
        <div v-if="type==='A'">优秀</div>
        <div v-else-if="type==='B'">良好</div>
        <div v-else-if="type==='C'">一般</div>
        <div v-else>差</div>
    </div>
    <script src="./lib/vue-2.6.12.js"></script>
    <script>
        const vm = new Vue({
            el: '#app',
            data: {
                /* 如果flag为true,则显示被控制的元素,若为false则隐藏被控制的元素,默认为true */
                flag: true,
                type: 'A'
            }
        })
    </script>

6.列表(循环)渲染指令(v-for)

vue 提供了v-for列表渲染指令,用来辅助开发者基于一个数组来循环渲染一个列表结构。v-for 指令需要使
用item in items 形式的特殊语法,其中:
  • items 是待循环的数组
  • item 是被循环的每一项
v-for 指令还支持一个可选的第二个参数,即当前项的索引。语法格式为(item,index)in items
注意:v-for 指令中的item index 索引都是形参,可以根据需要进行重命名。例如(user,i)in userlist
  • 列表的数据变化时,默认情况下,vue 尽可能的复用已存在的DOM 元素,从而提升渲染的性能。但这种默认的性能优化策略,会导致有状态的列表无法被正确更新
  • 为了给vue 一个提示,以便它能跟踪每个节点的身份,从而在保证有状态的列表被正确更新的前提下,提升渲染的性能。此时,需要为每项提供一个唯一的key 属性

6.1key 的注意事项

  • key 的值只能是字符串数字类型
  • key 的值必须具有唯一性(即:key 的值不能重复)
  • 建议把数据项id 属性的值作为key 的值(因为id 属性的值具有唯一性)
  • 使用index 的值当作key 的值没有任何意义(因为index 的值不具有唯一性)
  • 建议使用v-for 指令时一定要指定key 的值(既提升性能、又防止列表状态紊乱)
    <!-- 列表渲染指令v-for -->
    <div id="app">
        <table class="table table-bordered table-hover table-striped ">
            <thead>
                <th>索引</th>
                <th>ID</th>
                <th>姓名</th>
            </thead>
            <tbody>
                <!-- 建议:只要用到了v-for指令,那么一定要绑定一个:key属性 -->
                <!-- 而且,尽量把id作为key值 -->
                <!--官方对key的值类型,有要求,字符串或数字类型 -->
                <!-- key的值是千万不能重复的,否则会终端报错:Duplicate keys detected -->
                <tr v-for="(item,index) in list" :key="item.id">
                    <td>{{index}}</td>
                    <td>{{item.id }}</td>
                    <td>{{item.name}}</td>
                </tr>
            </tbody>
        </table>
    </div>
    <script src="./lib/vue-2.6.12.js"></script>
    <script>
        const vm = new Vue({
            el: '#app',
            data: {
                list: [{
                    id: 1,
                    name: '迪丽热巴'
                }, {
                    id: 2,
                    name: '李四'
                }, {
                    id: 3,
                    name: '张三'
                }]
            }
        })
    </script>

6.2 label的for属性

for的值等于checkbox的id属性进行绑定,可以实现点击标签label也能改变checkbox状态

  <input type="checkbox" id="cb1">
  <label for="cb1">男</label>
  <hr>
  <input type="checkbox" id="cb2">
  <label for="cb2">女</label>

6.3key的内部原理

面试题:react、vue中的key有什么作用?(key的内部原理

1. 虚拟DOM中key的作用:

  key是虚拟DOM对象的标识,当数据发生变化时,Vue会根据【新数据】生成【新的虚拟DOM】,

 随后Vue进行【新虚拟DOM】与【旧虚拟DOM】的差异比较,比较规则如下:

2.对比规则:

(1).旧虚拟DOM中找到了与新虚拟DOM相同的key:

  • ①.若虚拟DOM中内容没变, 直接使用之前的真实DOM!
  • ②.若虚拟DOM中内容变了, 则生成新的真实DOM,随后替换掉页面中之前的真实DOM。

(2).旧虚拟DOM中未找到与新虚拟DOM相同的key

  创建新的真实DOM,随后渲染到到页面。             

3. 用index作为key可能会引发的问题:

  • 若对数据进行:逆序添加、逆序删除等破坏顺序操作:会产生没有必要的真实DOM更新 ==> 界面效果没问题, 但效率低。
  • 如果结构中还包含输入类的DOM:会产生错误DOM更新 ==> 界面有问题。

 4. 开发中如何选择key?:

  • 1.最好使用每条数据的唯一标识作为key, 比如id、手机号、身份证号、学号等唯一值。
  • 2.如果不存在对数据的逆序添加、逆序删除等破坏顺序操作,仅用于渲染列表用于展示, 使用index作为key是没有问题的。

7.v-cloak指令(防止闪现, 与 css 配合: [v-cloak] { display: none }

本质是一个特殊属性,Vue实例创建完毕并接管容器后,会删掉v-cloak属性。

使用css配合v-cloak可以解决网速慢时页面展示出{{xxx}}的问题。

		<style>
			[v-cloak]{
				display:none;
			}
		</style>
		<!-- 引入Vue -->
	</head>
	<body>
		<div id="root">
			<h2 v-cloak>{{name}}</h2>
		</div>
		<script type="text/javascript" src="http://localhost:8080/resource/5s/vue.js"></script>
	</body>
	<script type="text/javascript">
		new Vue({
			el:'#root',
			data:{
				name:'迪丽热巴'
			}
		})
	</script>

8.v-once指令(初次动态渲染后不再改变)

  •   1.v-once所在节点在初次动态渲染后,就视为静态内容了。
  •   2.以后数据的改变不会引起v-once所在结构的更新,可以用于优化性能。


		<div id="root">
			<h2 v-once>初始化的n值是:{{n}}</h2>
			<h2>当前的n值是:{{n}}</h2>
			<button @click="n++">点我n+1</button>
		</div>

9.v-pre指令(被该指令用的vue不会去解析它)

  • 1.跳过其所在节点的编译过程。
  • 2.可利用它跳过:没有使用指令语法、没有使用插值语法的节点,会加快编译。

		<div id="root">
			<h2 >Vue其实很简单</h2>
			<h2 v-pre>当前的n值是:{{n}}</h2>
			<button @click="n++">点我n+1</button>
		</div>

列表案例

    <title>品牌列表案例</title>
    <link rel="stylesheet" href="./lib/bootstrap.css">
    <link rel="stylesheet" href="./css/brandlist.css">
</head>

<body>

    <div id="app">
        <!-- 卡片区域 -->
        <div class="card">
            <div class="card-header">
                添加品牌
            </div>
            <div class="card-body">
                <!-- 添加品牌的表单区域 -->
                <!-- form 表单元素有 submit 事件 -->
                <form @submit.prevent="add">
                    <div class="form-row align-items-center">
                        <div class="col-auto">
                            <div class="input-group mb-2">
                                <div class="input-group-prepend">
                                    <div class="input-group-text">品牌名称</div>
                                </div>
                                <input type="text" class="form-control" placeholder="请输入品牌名称" v-model.trim="brand">
                            </div>
                        </div>
                        <div class="col-auto">
                            <button type="submit" class="btn btn-primary mb-2">添加</button>
                        </div>
                    </div>
                </form>
            </div>
        </div>

        <!-- 表格区域 -->
        <table class="table table-bordered table-hover table-striped">
            <thead>
                <tr>
                    <th scope="col">#</th>
                    <th scope="col">品牌名称</th>
                    <th scope="col">状态</th>
                    <th scope="col">创建时间</th>
                    <th scope="col">操作</th>
                </tr>
            </thead>
            <tbody>
                <tr v-for="item in list" :key="item.id">
                    <td>{{ item.id }}</td>
                    <td>{{ item.name }}</td>
                    <td>
                        <div class="custom-control custom-switch">
                            <!-- 使用 v-model 实现双向数据绑定 -->
                            <input type="checkbox" class="custom-control-input" :id="'cb' + item.id" v-model="item.status">
                            <!-- 使用 v-if 结合 v-else 实现按需渲染 -->
                            <label class="custom-control-label" :for="'cb' + item.id" v-if="item.status">已启用</label>
                            <label class="custom-control-label" :for="'cb' + item.id" v-else>已禁用</label>
                        </div>
                    </td>
                    <td>{{ item.time }}</td>
                    <td>
                        <a href="javascript:;" @click="remove(item.id)">删除</a>
                    </td>
                </tr>
            </tbody>
        </table>
    </div>

    <script src="./lib/vue-2.6.12.js"></script>
    <script>
        const vm = new Vue({
            el: '#app',
            data: {
                // 用户输入的品牌名称
                brand: '',
                // nextId 是下一个,可用的 id
                nextId: 4,
                // 品牌的列表数据
                list: [{
                    id: 1,
                    name: '宝马',
                    status: true,
                    time: new Date()
                }, {
                    id: 2,
                    name: '奔驰',
                    status: false,
                    time: new Date()
                }, {
                    id: 3,
                    name: '奥迪',
                    status: true,
                    time: new Date()
                }, ],
            },
            methods: {
                // 点击链接,删除对应的品牌信息
                remove(id) {
                    this.list = this.list.filter(item => item.id !== id)
                },
                // 阻止表单的默认提交行为之后,触发 add 方法
                add() {
                    // 如果判断到 brand 的值为空字符串,则 return 出去
                    if (this.brand === '') return alert('必须填写品牌名称!')

                    // 如果没有被 return 出去,应该执行添加的逻辑
                    // 1. 先把要添加的品牌对象,整理出来
                    const obj = {
                            id: this.nextId,
                            name: this.brand,
                            status: true,
                            time: new Date()
                        }
                        // 2. 往 this.list 数组中 push 步骤 1 中得到的对象
                    this.list.push(obj)
                        // 3. 清空 this.brand;让 this.nextId 自增 +1
                    this.brand = ''
                    this.nextId++
                }
            },
        })
    </script>
</body>

</html>

Vue中的数据代理

1.Object.defineProperty方法

/* 双向绑定原理数据劫持 v-model */
let number = 18
let person = {
name:'张三',
sex:'男',
}

Object.defineProperty(person,'age',{
// value:18,
// enumerable:true, //控制属性是否可以枚举,默认值是false
// writable:true, //控制属性是否可以被修改,默认值是false
// configurable:true //控制属性是否可以被删除,默认值是false

//当有人读取person的age属性时,
get函数(getter)就会被调用,
且返回值就是age的值
get(){
console.log('有人读取age属性了')
return number
},
//当有人修改person的age属性时,
set函数(setter)就会被调用,且会收到修改的具体值
set(value){
console.log('有人修改了age属性,且值是',value)
number = value
}

})

// console.log(Object.keys(person))
console.log(person)

2.数据代理:通过一个对象代理对另一个对象中属性的操作

let obj = {x:100}
let obj2 = {y:200}

Object.defineProperty(obj2,'x',{
	get(){
		return obj.x
	},
	set(value){
		obj.x = value
	}
})

3.Vue的数据代理

  • Vue中的数据代理:

      通过vm对象来代理data对象中属性的操作(读/写)

  • Vue中数据代理的好处:

      更加方便的操作data中的数据

  • 基本原理:

      通过Object.defineProperty()把data对象中所有属性添加到vm上。

      为每一个添加到vm上的属性,都指定一个getter/setter。

      在getter/setter内部去操作(读/写)data中对应的属性。

Vue的数据监测

1. vue会监视data中所有层次的数据。

2. 如何监测对象中的数据?

 通过setter实现监视,且要在new Vue时就传入要监测的数据。

(1).对象中后追加的属性,Vue默认不做响应式处理

 (2).如需给后添加的属性做响应式,请使用如下API:

 Vue.set(target,propertyName/index,value) 或 vm.$set(target,propertyName/index,value)

 3. 如何监测数组中的数据?

通过包裹数组更新元素的方法实现,本质就是做了两件事:

  •  (1).调用原生对应的方法对数组进行更新。
  •  (2).重新解析模板,进而更新页面。

 4.在Vue修改数组中的某个元素一定要用如下方法:

  • 1.使用这些API:push()、pop()、shift()、unshift()、splice()、sort()、reverse()
  •  2.Vue.set() 或 vm.$set()

特别注意:Vue.set() 和 vm.$set() 不能给vm 或 vm的根数据对象 添加属性!!

	<script type="text/javascript">
		Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。

		const vm = new Vue({
			el:'#root',
			data:{
				student:{
					name:'tom',
					age:18,
					hobby:['抽烟','喝酒','烫头'],
					friends:[
						{name:'jerry',age:35},
						{name:'tony',age:36}
					]
				}
			},
			methods: {
				/* 修改对象 */
				addSex(){
					// Vue.set(this.student,'sex','男')
					this.$set(this.student,'sex','男')
				},
				addFriend(){
					this.student.friends.unshift({name:'jack',age:70})
				},
				updateFirstFriendName(){
					this.student.friends[0].name = '张三'
				},
				/* 修改数组 */
				addHobby(){
					this.student.hobby.push('学习')
				},
				updateHobby(){
					// this.student.hobby.splice(0,1,'开车')
					// Vue.set(this.student.hobby,0,'开车')
					this.$set(this.student.hobby,0,'开车')
				},
				removeSmoke(){
					this.student.hobby = this.student.hobby.filter((h)=>{
						return h !== '抽烟'
					})
				}
			}
		})
	</script>

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 监听Vue数据是指通过Vue提供的监听方法,可以实时监测数据的变化并做出相应的操作。在Vue中,我们可以使用watch来监听数据的变化。 通过在Vue实例中使用watch属性,我们可以将要监听的数据以字符串形式传递给watch,并在watch中定义一个函数,当数据发生变化时,该函数就会被触发。 例如,假设我们要监听一个叫做"count"的数据,可以在Vue实例中添加如下代码: ``` watch: { count(newValue, oldValue) { console.log('count的值发生变化啦!新的值为:' + newValue + ',旧的值为:' + oldValue); // 可以在这里执行一些自定义的操作 } } ``` 在上述代码中,我们在watch属性中定义了一个count函数,当count数据发生变化时,该函数会被触发。在函数体中,我们可以获取到变化后的新值和变化前的旧值,并可以在这里执行一些自定义的操作。 监听Vue数据可以帮助我们实时获取数据的变化情况,以便及时做出响应。这对于一些需要实时更新数据的场景非常有用,比如当数据发生变化时,我们需要根据新的数据进行计算、展示等操作。 总之,通过监听Vue数据,我们可以在数据变化时得到通知,并进行相应的处理,从而实现数据的实时更新及操作。 ### 回答2: Vue是一种用于构建用户界面的渐进式JavaScript框架。它通过数据驱动和组件化的方式使得开发者可以简单、高效地构建可复用的UI组件。Vue数据监听机制是其核心特性之一。 Vue通过采用响应式的数据绑定机制来监听数据的变化。当一个数据被绑定到Vue实例中的属性时,Vue会将这个属性转化为getter/setter,并且在需要的时候收集依赖和触发更新。这个机制可以让Vue追踪到每个属性的依赖关系,并在属性发生变化时自动更新有关联的组件。 Vue实现数据监听的方式主要有两种:Object.defineProperty和Proxy。在较低版本的浏览器中,Vue使用Object.defineProperty来实现数据监听。它通过重写对象属性的getter和setter来实现依赖追踪和更新通知。在较新版本的浏览器中,Vue使用Proxy来实现数据监听。Proxy可以劫持整个对象,不需要像Object.defineProperty那样重写getter和setter。 对于Vue来说,数据监听是非常重要的,它可以让开发者编写的代码更具有可维护性和可复用性。当数据发生变化时,Vue会自动检测到这些变化并更新相关的组件,从而实现了数据和视图的双向绑定。这种自动化的数据监听机制可以极大地减少开发者的工作量,提高开发效率。 以一个简单示例来说明数据监听的实现方式。假设有一个Vue实例: ```javascript var vm = new Vue({ data: { message: 'Hello Vue!' } }) ``` 当我们修改`data`中的`message`属性时,例如: ```javascript vm.message = 'Hello World!' ``` Vue会自动检测到`message`属性的变化,并更新对应的组件。在这个示例中,Vue会将`message`属性转化为getter/setter,并在需要的时候触发组件的更新操作,使得界面中显示的内容变为新的值。 综上所述,Vue数据监听机制是通过响应式的数据绑定方式来实现的,它是Vue框架的核心特性之一,能够实现数据和视图的自动更新,提高开发效率和减少工作量。 ### 回答3: Vue 是一种用于构建用户界面的渐进式JavaScript框架。它包含了一系列的工具和库,使开发人员能够轻松地构建复杂的单页应用程序。Vue 提供了一种数据监听的机制,可以实时地追踪和更新数据的变化。 Vue数据监听是通过Vue实例中的数据属性来实现的。当数据发生变化时,Vue会自动检测到变化并更新相应的视图。这种监听机制可以确保视图与数据的同步,使开发者能够更加便捷地操作数据和界面。 Vue提供了多种监听数据变化的方式。最常见的方式是使用`v-model`指令数据绑定到表单元素上,当表单数据发生变化时,Vue会自动更新与之绑定的数据属性。此外,Vue还提供了`watch`属性,可以监听指定数据的变化并执行相应的回调函数。通过`computed`属性,Vue还可以创建计算属性,实时计算数据依赖关系。 除了上述常用方式外,Vue还提供了更高级的数据监听功能。开发者可以使用`$watch`方法手动监听数据的变化。使用该方法,可以监听具体的属性变化,也可以监听整个数据对象的变化。这种方式可以更加灵活地对数据进行监听和操作。 总而言之,Vue提供了灵活而强大的数据监听功能,使开发者能够方便地追踪和处理数据的变化。这为开发人员提供了更好的开发体验和更快速的应用程序开发。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值