㈠ watch和computed的区别
计侍衡余算属性通常依赖于其他数据属性。对于依赖属性的任何改变都会触发计算属性的逻辑。计算属性基于它们的依赖关系进行缓存,因此只有当依赖项发生变化时,它们才会重新运行,否则他会使用缓存中的属性值。(例如,返回 new Date()的计算属性将永远不会重新运行,因为逻辑将不会运行超过一次)。计算属性在默认情况下是getters,但是如果需要实现类似的功能,则可以设置setter函数。
计算属性将被混入到 Vue 实例中。所有 getter 和 setter 的 this 上下文自动地绑定为 Vue 实例。
watch:
watch用来监听当一个数据属性值发生变化时,就可以调用的函数,没有必须依赖的数据属性;属于异步操作;
Vue 实例将会在实例化时调用 $watch(),遍历 watch 对象的每一个属性。
举个拦举栗子
但数据量较大的时候,用watch更合适;在过滤数据的时候用computed。
computed的基础用法:
计算属性的getter函数---当其依赖的属性的值发生变化的时,这个计算属性的值也会自动更新。多用于"data,computed"的属性。
计算属性的setter函数---当赋值给计算属性的时候,将调用setter函数。多用于在模板组件中需要修改计算属性自身的值的时候,例子如下:
计算属性的缓存---Vue实例中被观察的数据属性发生了改变时老滚才会重新执行getter,但是我们有时候计算属性依赖实时的非观察数据属性,比如下面例子中的Data.now
计算属性getter不执行的场景---当包含计算属性的节点被移除并且模板中其他地方没有再引用该属性的时候,那么对应的计算属性的getter函数方法不会执行
在v-for中使用计算属性,起到类似"过滤器的作用",例子如下:
watch与computed的set函数的比较---uex 接收 的computed ,用set监测不到变化,必须要用watch才可以生效;(原理:实质没有改变computd的值,只是改变了get的return值 => 组件外的访问)
v-model 改变的computed,用watch监测不到变化,必须要用computed对象中的set函数方法才能监测得到(原理:相当于每次改变了computed自身的值 => 组件内的访问)
computed和watch都不可用箭头函数,因为箭头函数绑定了父级作用域的上下文,所以 this 将不会按照期望指向 Vue 实例,this.a 将是 undefined。
父组件通过props向子组件传入的值,在子组件中是不可修改的,不然会报错,但是如果需要根据页面需求对props传入的值进行修改的话,则可以在data中重新定义一个变量,改变指向,通过watch来监测props值的改变,并实时修改data中变量的值,例子如下:
这里 watch 的一个特点是,最初绑定的时候是不会执行的,要等到 firstName 改变时才执行监听计算。
那我们想要一开始就让他最初绑定的时候就执行改immediate: true。
handler,Vue.js会去处理这个逻辑,最终编译出来其实就是这个handler。
deep的意思就是深入观察,监听器会一层层的往下遍历,给对象的所有属性都加上这个监听器,但是这样性能开销就会非常大了,任何修改里面任何一个属性都会触发这个监听器里的 handler。
举个栗子:
㈡ vue.js中,什么时候用methods什么时候用computed什么时候用watch
1、methods是个方法,比如你点击事件要执行一个方法,这时候就用methods,
2、computed是计算属性,实时响应的,比如你李源铅要根据data里一个值随时变化做出一些处理,就用computed。
3、举一个例子帮助理解:
1)裂哗<div id="root">;
2) </div>;
3) <script> var vm = new Vue({ el: '#root', data:data, methods:{
4)method_now(){ return Date.now();} },
5)computed:{
6)computed_now: function () { return Date.now();}} })
7)</script>
4、控制台访问:
1)$vm0.computed_now;
2)1491741921719$vm0.computed_now;
3)1491741921719$vm0.computed_now;
4)1491741921719$vm0.computed_now;
5)1491741921719$vm0.method_now;
6)()1491741949941$vm0.method_now;
7)()1491741950734$vm0.method_now;
8)()1491741951445$vm0.method_now;
9)()1491741952117。
5、methods是方法和原生js没区别,大多是需要我们主动调用(比如事件)。
6、computed是get 这个get有点特殊,只要触发所依赖数据的set会自动触发get。我们哪好只关心get的return set由系统触发或者依赖的数据触发,官方说依赖缓存只是为了理解。其实Date.now()这种只是系统不能触发set,不能触发set get当然不会通知观察者。
7、watch 是set 由data触发,我们可以在set里进行自己的条件封装。
㈢ vue怎么学
如果你是 Vue 开发新手,可能已经听过很多行话术语,比如单页面姿亩激应用程序、异步组件、服务器端渲染,等等。你可能还听说过与 Vue 有关的一些工具和库,比如 Vuex、Webpack、Vue CLI 和 Nuxt。
浸没在术语和工具的浩瀚海洋中难免会令人感到沮丧,但其实并不是只有你一个人有这种感受,所有经验水平的开发人员都会持续感觉到这种莫名的压力。分享一张图给你看看
基础知识:
vue的生命迹袜周期: beforeCreate/created、 beforeMount/mounted、 beforeUpdate/updated、 beforeDestory/destoryed
vue常用指令: v-for、 v-bind(缩写形式 :prop)、 v-on(缩写形式 @click=’sss')、 v-if/v-else/v-else-if、 v-model、 v-once、 v-html、 v-show...
vue自定义组件: Vue.component(‘componentName',{ props:[‘p1’,’p2’], template: ‘<li>{{ p1 }}</li>'})
vue常用实例方法和属性: data/$data、 methods/$methods、 $el、 computed(计算属性)、 $watch、 $set、 $event、 $emit...
如果需要更新的属性需要缓存,则使用计算属性的方式,否则可以使用 methods里的方法来更新属性( methods里的方法每次重新渲染都会执行)
计算属性默认提供了 getter,你还可以给它设耐友置 setter
当你数据变化是异步或者开销较大时,可以使用 watch侦听器来响应数据的变化
v-bind:class的值可以是一个对象,可实现类似 react中 classnames模块的功能
自定义组件上的 class会被渲染拼接到 template的根节点的 class属性上(自定义组件上可使用 v-bind:class来做class的判断显示逻辑)
v-bind:style可以用来绑定内联样式,这个内联样式的值可以由一个对象来定义(类似css in js的模式),且可以被定义为数组(多个样式对象)
v-bind:style可以使用多重值的形式: <div:style=“display:[‘-webkit-box’,’-ms-flexbox’,‘flex']"></div>
v-if/v-else/v-else-if的时候,可以用key来管理可复用的元素
v-if是’真正’的渲染,它会确保在切换条件过程中条件块内的元素的事件监听器和子组件适时的销毁和重建
v-if是惰性的,初始为假,什么也不做,直到为真的时候才渲染元素
v-show总是渲染元素,只是简单的进行切换
v-if的切换开销大, v-show则是初始渲染开销大,频繁切换使用 v-show,运行时经常改变则使用 v-if
v-if和 v-for一起使用时, v-for的优先级更高
v-for可遍历数组,第二个参数是索引
v-for可遍历对象,第二个参数是 key,第三个参数是索引
v-for和 <template>搭配可减少渲染次数
v-for和自定义组件使用时,需要使用 props来传递值
尽可能的为遍历子元素加上 key,获得渲染优化
数组变异方法: push/pop/unshift/shift/splice/sort/reverse改变原始数组
数组非变异方法: filter/concat/slice 不改变原始数组,总是返回新数组
Vue不能检测到数组索引赋值(使用 vm.$set解决)和修改 length长度赋值(使用 splice解决)的情况
Vue不能检测对象属性的添加和删除(使用 vm.$set或 Object.assign)
is=“todo-item”这种属性的写法比较适合DOM模板
事件修饰符,它们可串联使用: .stop、 .prevent、 .capture、 .self、 .once、 .passive(尤其适合移动端)
.passive不用同时和 .prevent使用,后者会被忽略
按键修饰符: .enter、 .tab、 .delete、 .esc、 .space、 .up、 .down、 .left、 .right
系统按键修饰符: .ctrl、 .alt、 .shift、 .meta(⌘|⊞|◆)、 .exact(允许精确控制系统修饰符组合键触发)
鼠标修饰符: .left、 .right、 .middle
v-model会忽略表单元素的 value、 checked、 selected,仅仅使用实例中的数据作为数据源
表单事件修饰符: .lazy、 .number、 .trim
组件是可复用的vue实例,具有vue实例大多数属性和方法
组件可复用,每个组件有独立的空间
组件上的data必须是一个函数,这样做避免影响了其他组件
通过 Vue.component()全局注册的组件可在其被注册后的任何通过 newVue()创建的实例所使用,包含其组件树中的所有组件
通过插槽 <slot>分发内容(其实就是类似于react的children)
动态组件 <component>配合属性 is来实现
解析DOM模板时需要注意下可能会有不生效的情况,需要使用is来传递组件
㈣ vue是如何避免重复渲染的
上一篇 vue双向绑定原理源码解析
上一篇文章我们说了vue双向绑定原理,每个watcher对象都绑定了唯一的id,当组件props和data对象属性发生变化时,将会携虚触发watcher对象update方法,
lazy属性是避免computed属迟散性里用到(props和data)对象属性变化导致的重复调用update
默认情况下watcher对象的sync是false,会调用queueWatcher方法
这个方法里主要判断了当前工作队列中是否已经有这个watcher对象,辩旦燃
如果工作队列中没有此而且队列也还没开始执行,加到队列中去。
如果工作队列中没有watcher对象,但是队列已经开始执行,如果插入位置小于等于当前正在执行的warcher位置,则插入当前的执行warcher的后面。如果插入位置大于当前正在执行的warcher位置,则比较执行位置index后面watcher的id 和 传入watcher的id
nextTick是异步执行方法,vue对此进行了封装,针对不同浏览器对js原生异步的函数的支持,简单点理解就是一个setTimeout方法
因为是异步执行方法,所以在主线程的方法执行完,才执行任务队列中flushSchelerQueue,
下面我们来看一个列子:
测试下来name属性变化了三次,但是只触发了一次更新。我们来分析一下原因:
name属性第一次改变时,queue中插入 name属性里Dep对象下的所有watcher对象,因主线程函数并没执行完,此时flushSchelerQueue方法还在等待
name属性第二次改变时,queue中并没有插入name属性里Dep对象下的所有watcher对象,此时flushSchelerQueue方法还在等待
name属性第三次改变时,queue中还是没有插入name属性里Dep对象下的所有watcher对象,此时主线程函数执行完毕,回调任务队列中flushSchelerQueue方法,更新视图