数据与方法
📒当一个vue实例被创建时,它向vue响应式系统中加入了其data能找到的所有的属性,当这些属性值变化时,视图将会响应。
是创建的时候才会去监听,数据才是响应式的。如果在创建之后向一个对象中添加一个属性,这个属性不会被监听到,不是响应式的。在创建对象的时候,如果能预计有什么属性,应该先初始化对象,设置一些初始值。
📒 Object.freeze()会冻结一个对像,阻止修改现有的对象。如果使用了和这个方法,页面不会再监听这个对象了。
📒 不要在选项属性或者回调函数上使用箭头函数。箭头函数是和父级上下文绑定的,this在所有的生命周期中,不一定是指向vue实例。
📒 v-once: 一次性的绑定值,当数据改变的时候,不会再随之变化了,
📒 在模板中放入太多的逻辑会让模板过重且难以维护。对于复杂的逻辑,不推荐放在模版里面,应该使用计算属性
计算属性&&方法&&watch
📒 计算属性是基于依赖来进行缓存的。只有在相关的依赖发生变化的时候才会重新计算。方法其实可以得到和计算属性相同的结果。
不同的是,计算属性在依赖没有变化的时候,不会更新,有缓存。
📒 缓存的意义:如果有个结果计算会消耗大量的性能才能计算出来,如果使用函数,那每次调用这个结果都要执行一次函数,性能消耗打,使用
计算属性,在其中依赖没有变化的时候不会重新计算,性能消耗比较小
📒 watch:当需要在数据变化时执行异步或者开销比较大的操作使用
📒 在写代码的时候,如果某个结果依赖一个值的变化,并且计算这个结果比较复杂,推荐使用计算属性。要善用计算属性。
class && style
📒 尽量不要写在模版里面,模版应该是简洁的。
<div v-bind:class="classObject"></div>
data: {
isActive: true,
error: null
},
computed: {
classObject: function () {
return {
active: this.isActive && !this.error,
'text-danger': this.error && this.error.type === 'fatal'
}
}
}
v-if && v-show
- v-if:有很高的切换开销,在运行切换少的情况下推荐使用
- v-show: 初始渲染开销高, 在频繁切换的时候推荐使用
📒 v-if和v-for一起使用的时候,v-for优先级比v-if高
v-for
📒 可以通过一个对象来迭代,第二个参数为键名,第三个参数为索引
<div v-for="(value, key, index) in object">
{{index}}{{ key }}: {{ value }}
</div>
new Vue({
el: '#v-for-object',
data: {
object: {
firstName: 'John',
lastName: 'Doe',
age: 30
}
}
})
📒 “就地复用”策略:
当 Vue.js 用 v-for 正在更新已渲染过的元素列表时,它默认用“就地复用”策略。如果数据项的顺序被改变,Vue 将不会移动 DOM 元素来匹配数据项的顺序, 而是简单复用此处每个元素,并且确保它在特定索引下显示已被渲染过的每个元素。这个类似 Vue 1.x 的 track-by=”$index” 。
📒 v-for可以使用方法:可以用来过滤处理数据了
<li v-for="n in even(numbers)">{{ n }}</li>
data: {
numbers: [ 1, 2, 3, 4, 5 ]
},
methods: {
even: function (numbers) {
return numbers.filter(function (number) {
return number % 2 === 0
})
}
}
key
作用:主要是为了高效的更新虚拟DOM。提高遍历性能。另外vue中在使用相同标签名元素的过渡切换时,也会使用到key属性,其目的也是为了让vue可以区分它们,否则vue只会替换其内部属性而不会触发过渡效果。
- 两个相同的组件产生类似的DOM结构,不同的组件产生不同的DOM结构。
- 同一层级的一组节点,他们可以通过唯一的id进行区分。
当页面的数据发生变化时,Diff算法只会比较同一层级的节点:如果节点类型不同,直接干掉前面的节点,再创建并插入新的节点,不会再比较这个节点以后的子节点了。如果节点类型相同,则会重新设置该节点的属性,从而实现节点的更新。当某一层有很多相同的节点时,也就是列表节点时,Diff算法的更新过程默认情况下也是遵循以上原则。
数组更新检测
以下变异方法可以触发视图更新
- push()
- pop()
- shift()
- unshift()
- splice()
- sort()
- reverse()
⚠️ 以下几种方法不能检测数组变化:
- 当你利用索引直接设置一个项时,例如:
vm.items[indexOfItem] = newValue
- 当你修改数组的长度时,例如:
vm.items.length = newLength
解决方法:
Vue.set(vm.items, indexOfItem, newValue)
vm.items.splice(indexOfItem, 1, newValue)
📒 vue不能检测对象属性的添加或者删除
解决方法:
- 通过vue.set
- 使用Object.assgin或者_.extends(),创建新对象
事件处理
📒 在方法中传入$event,可以访问DOM原生事件对象
<button v-on:click="warn($event)">
Submit
</button>
📒 事件修饰符
表单输入绑定
📒 v-model不会在输入法组合文字过程中更新,可以使用input来监听这个过程。
📒修饰符:
- .lazy: v-model内容change的时候更新,而不是input的时候更新
- .number
- .trim
组件
📒 动态组件:通过is绑定组件名称, 有些标签里面只能使用固定标签,不能直接写组件名称,可以通过is来使用组件
<!-- 组件会在 `currentTabComponent` 改变时改变 -->
<component v-bind:is="currentTabComponent"></component>
<table>
<tr is="blog-post-row"></tr>
</table>
📒 全局注册的行为必须在根 Vue 实例 (通过 new Vue) 创建之前发生
props
📒 props是通过引用传入的,所以子组件修改会影响父组件的变化
📒 prop 会在一个组件实例创建之前进行验证 (beforeCreated)
📒 interitAttrs
在版本 2.4 之前,默认情况下父作用域的不被作为props特性绑定的属性,将会作为普通的 HTML 属性,应用在跟元素上。设置 interitAttrs 为 false,之后,不会应用到跟元素上。
// parent.vue
<template>
<child-commpent :foo="f" :boo="b"></child-comment>
</template>
<script>
const childComment = () => import('./childCom.vue')
export default {
data () {
return {
f: 'Hello world!'
b: 'Hello Vue!'
}
}
}
// childComment.vue
<template>
<div>{{ foo }}<div>
</template>
<script>
export default {
props: ['foo']
}
</script>
</script>
最后会被渲染城这样:
<div boo="Hello Vue!">Hello world!</div>
设置 interitAttrs 为 false
export default {
props: ['foo'],
interitAttrs: false
}
渲染结果:
<div>Hello world!</div>
📒 $attrs
使用 v-bind=”$attrs”, 将父组件中不被认为 props特性绑定的属性传入子组件中,通常配合 interitAttrs 选项一起使用
<template>
<child-commpent :foo="f" :boo="b" coo="c"></child-comment>
</template>
<script>
const childComment = () => import('./childCom.vue')
export default {
data () {
return {
f: 'Hello world!'
b: 'Hello Vue!',
c: 'Hello'
}
}
}
</script>
// childComment.vue
<template>
<div>{{ foo }}<div>
<p>attrs: {{ $attrs }}</p>
</template>
<script>
export default {
props: ['foo'],
interitAttrs: false
}
</script>
渲染结果:
Hello world!
Hello Vue!, Hello
📒 props可以以字符串数组的形式列出
自定义的v-model
边界处理情况
📒 $refs 只会在组件渲染完成之后生效,并且它们不是响应式的。这只意味着一个直接的子组件封装的“逃生舱”——你应该避免在模板或计算属性中访问 $refs。
keep-alive
📒 keep-alive组件可以记住包含组件的状态
nextTick
在修改数据之后立即调用这个函数,可以获取更新后的DOM,如果需要DOM更新后进行一些操作,可以使用这个函数
mixins
数据的优先级比组件内部定义的低
同名钩子函数混合成一个数组,混入对象的钩子比组件内部定义的钩子先执行
渲染函数&& jsx
虚拟DOM更新页面节点
vue不能检测对象属性的添加和删除,可以通过vue.set(obj, key, value)来添加属性
.sync
提供对于 prop 的双向绑定。
<child :bar.sync="foo"></child>
其实是个语法糖
<child :bar="foo" @update:bar="e => foo = e">
此时需要在子组件中显示触发事件:
this.$emit('update:bar', newValue)
获取表单数据
获取同时还可以给变量一个初始值
const { userName, password, checked = [] } = this.form
template && render
当Vue选项对象中有render渲染函数时,Vue构造函数将直接使用渲染函数渲染DOM树,
当选项对象中没有render渲染函数时,Vue构造函数首先通过将template模板生成render函数,然后再渲染DOM树,
而当选项对象中既没有render渲染函数,也没有template模板时,会通过el属性获取挂载元素的outerHTML来作为模板,并编译生成渲染函数。
如果 Vue 选项中包含渲染函数,该模板将被忽略。
Vue 选项中的 render 函数若存在,则 Vue 构造函数不会从 template 选项或通过 el 选项指定的挂载元素中提取出的 HTML 模板编译渲染函数。
进行DOM渲染的时候,render函数优先级最高,template和el次之。最终得到的都是render函数
在实例挂载之后,元素可以用vm.$el访问
未完。。。