从官网上整理的
一
MVVM
二
JavaScript由什么构成
三
声明式编程与命令是编程
vue 响应式:当一个 Vue 实例被创建时,它将 data
对象中的所有的 property 加入到 Vue 的响应式系统中。当这些 property 的值发生改变时,视图将会产生“响应”,即匹配更新为新的值
四 简单结构
命名:
html-》强制小写,在 DOM 中使用模板时 (直接在一个 HTML 文件里撰写模板),还需要避免使用大写字符来命名键名,因为浏览器会把 attribute 名全部强制转为小写:
动态参数表达式有一些语法约束,因为某些字符,如空格和引号,放在 HTML attribute 名里是无效的。例如:
<!-- 这会触发一个编译警告 -->
<a v-bind:['foo' + bar]="value"> ... </a>
变通的办法是使用没有空格或引号的表达式,或用计算属性替代这种复杂表达式。
css-》CSS property 名可以用驼峰式 (camelCase) 或短横线分隔 (kebab-case,记得用引号括起来) 来命名
通常
var vm = new Vue({
el
提供一个在页面上已存在的 DOM 元素作为 Vue 实例的挂载目标。可以是 CSS 选择器,也可以是一个 HTMLElement 实例。
如果在实例化时存在这个选项,实例将立即进入编译过程,否则,需要显式调用
vm.$mount()
手动开启编译。
data:
Vue 实例的数据对象。Vue 会递归地把 data 的 property 转换为 getter/setter,从而让 data 的 property 能够响应数据变化,当一个组件被定义,
data
必须声明为返回一个初始数据对象的函数,因为组件可能被用来创建多个实例。如果data
仍然是一个纯粹的对象,则所有的实例将共享引用同一个数据对象!通过提供data
函数,每次创建一个新实例后,我们能够调用data
函数,从而返回初始数据的一个全新副本数据对象。
props:
数组或对象,用于接收来自父组件的数据,如:
props: { age: { type: Number,检测类型 default: 0,指定一个默认值 required: true,定义该 prop 是否是必填项 validator: function (value) { 自定义验证函数会将该 prop 的值作为唯一的参数代入 return value >= 0 } } }
创建实例时传递 props。主要作用是方便测试。
computed:
计算属性将被混入到 Vue 实例中。所有 getter 和 setter 的 this 上下文自动地绑定为 Vue 实例。
注意如果你为一个计算属性使用了箭头函数,则
this
不会指向这个组件的实例计算属性的结果会被缓存,除非依赖的响应式 property (比如data中某个值)变化才会重新计算
Date.now()
不是响应式依赖:computed: {
now: function () {
return Date.now()
} }这样不行
计算属性默认只有 getter,不过在需要时你也可以提供一个 setter
watch:
一个对象,键是需要观察的表达式,值是对应回调函数。值也可以是方法名(),或者包含选项的对象。
watch: { a: function (val, oldVal) { //回调函数 console.log('new: %s, old: %s', val, oldVal) }, // 方法名 b: 'someMethod', // 该回调会在任何被侦听的对象的 property 改变时被调用,不论其被嵌套多深 c: {//对象 handler: function (val, oldVal) { /* ... */ }, deep: true }, // 你可以传入回调数组,它们会被逐一调用 e: [ 'handle1', function handle2 (val, oldVal) { /* ... */ }, { handler: function handle3 (val, oldVal) { /* ... */ }, /* ... */ } ], }
有额外选项deep:发现对象内部值的变化 immediate:立即以表达式的当前值触发回调
methods:
方法中的
this
自动绑定为 Vue 实例
生命周期钩子函数:
最常用:created,mounted
filter:
directives:
})
自定义
自定义指令directive Vue.directive(
对普通 DOM 元素进行底层操作
// 注册一个全局自定义指令 `v-focus` Vue.directive('focus', { // 当被绑定的元素插入到 DOM 中时…… inserted: function (el) { // 聚焦元素 el.focus() } }) //局部 directives: { focus: { // 指令的定义 inserted: function (el) { el.focus() } } }
钩子函数:
bind,inserted,update,componentUpdated,unbind
钩子函数参数
el,binding(里面内容name,value,oldValue,expression,arg,modifiers),vnode,oldVnode
template:
一个字符串模板作为 Vue 实例的标识使用。模板将会替换挂载的元素。挂载元素的内容都将被忽略,除非模板的内容有分发插槽。
render:
’字符串模板的代替方案,允许你发挥 JavaScript 最大的编程能力。该渲染函数接收一个
createElement
方法作为第一个参数用来创建VNode
。如果组件是一个函数组件,渲染函数还会接收一个额外的
context
参数,为没有实例的函数组件提供上下文信息。Vue 选项中的
render
函数若存在,则 Vue 构造函数不会从template
选项或通过el
选项指定的挂载元素中提取出的 HTML 模板编译渲染函数。
renderError
当
render
函数遭遇错误时,提供另外一种渲染输出。
自定义过滤器,
可被用于一些常见的文本格式化。过滤器可以用在两个地方:双花括号插值和
v-bind
表达式{{ message | filterA('arg1', arg2) }}
过滤器函数总接收表达式的值 (之前的操作链的结果) 作为第一个参数。这里,
filterA
被定义为接收三个参数的过滤器函数。其中message
的值作为第一个参数,普通字符串'arg1'
作为第二个参数,表达式arg2
的值作为第三个参数。
其他
class和style绑定
v-bind:class=可以是一个对象或数组等
五
模板语法:
- 插值:文本,html,attribute ,JavaScript
- 指令(v-):参数(如:v-bind:href,这个href就是参数 attribute ),动态参数(【】),修饰符(.stop,.prevent,.capture,.self,.once,.passive)顺序很重要,按键修饰符(
.enter
.tab.delete
(捕获“删除”和“退格”键).esc.space.up.down.left.right,可
通过全局config.keyCodes
对象自定义按键修饰符别名),系统修饰符(.ctrl
.alt
.shift
.meta
.exact(精准修饰)) - 缩写 :与@
计算属性和数据和watch:
- 计算属性:有缓存
- data:可以是对象,数组等
- watch:可以监听data中的数据,进行异步操作
v-if
- key可以管理可以复用的元素,即key的值代表元素的唯一的·还是重用的。
- 把一个 元素当做不可见的包裹元素,并在上面使用
v-if
。最终的渲染结果将不包含 元素。
v-show
- 带有
v-show
的元素始终会被渲染并保留在 DOM 中。v-show
只是简单地切换元素的 CSS propertydisplay
。v-show
不支持 元素,也不支持v-else
不同:v-if
是“真正”的条件渲染,因为它会确保在切换过程中条件块内的事件监听器和子组件适当地被销毁和重建。v-show
就简单得多——不管初始条件是什么,元素总是会被渲染,并且只是简单地基于 CSS 进行切换。一般来说,v-if
有更高的切换开销,而 v-show
有更高的初始渲染开销。因此,如果需要非常频繁地切换,则使用 v-show
较好;如果在运行时条件很少改变,则使用 v-if
较好。
注:v-for
具有比 v-if
更高的优先级。不推荐同时使用两者
v-for
- 用法:v-for="(item, index(这个可选)) in items",可以用
of
替代in
作为分隔符,itemsshi1数组- 在
v-for
块中,我们可以访问所有父作用域的 property。即items所在data中的数据- (value, name, index) in object ,object是对象
注:
当 Vue 正在更新使用
v-for
渲染的元素列表时,它默认使用“就地更新”的策略。如果数据项的顺序被改变,Vue 将不会移动 DOM 元素来匹配数据项的顺序,而是就地更新每个元素,并且确保它们在每个索引位置正确渲染。这个类似 Vue 1.x 的track-by="$index"
。这个默认的模式是高效的,但是只适用于不依赖子组件状态或临时 DOM 状态 (例如:表单输入值) 的列表渲染输出。
为了给 Vue 一个提示,以便它能跟踪每个节点的身份,从而重用和重新排序现有元素,你需要为每项提供一个唯一
key
attribute:
key
的特殊 attribute 主要用在 Vue 的虚拟 DOM 算法,在新旧 nodes 对比时辨识 VNodes。如果不使用 key,Vue 会使用一种最大限度减少动态元素并且尽可能的尝试就地修改/复用相同类型元素的算法。而使用 key 时,它会基于 key 的变化重新排列元素顺序,并且会移除 key 不存在的元素。数组的更新检测
变更方法(变更调用了这些方法的原始数组,会触发视图更新):push(),pop(),shift(),unshift(),splice(),sort(),reverse()
替换数组(不会变更原始数组,而总是返回一个新数组):filter(),concat(),slice()。你可能认为这将导致 Vue 丢弃现有 DOM 并重新渲染整个列表。幸运的是,事实并非如此。Vue 为了使得 DOM 元素得到最大范围的重用而实现了一些智能的启发式方法,所以用一个含有相同元素的数组去替换原来的数组是非常高效的操作。
由于 JavaScript 的限制,Vue 不能检测数组和对象的变化
解决办法:
对于对象:Vue 无法检测 property 的添加或移除。所以property 必须在
data
对象上存在,对于已经创建的实例,Vue 不允许动态添加根级别的响应式 property。但是,可以使用Vue.set(object, propertyName, value)
方法向嵌套对象添加响应式 property。有时你可能需要为已有对象赋值多个新 property,比如使用
Object.assign()
或_.extend()
。但是,这样添加到对象上的新 property 不会触发更新。在这种情况下,你应该用原对象与要混合进去的对象的 property 一起创建一个新的对象。// 代替 `Object.assign(this.someObject, { a: 1, b: 2 })` this.someObject = Object.assign({}, this.someObject, { a: 1, b: 2 })
对于数组:
不能检测到如下变动
- 当你利用索引直接设置一个数组项时,例如:
vm.items[indexOfItem] = newValue
- 当你修改数组的长度时,例如:
vm.items.length = newLength
为了解决第一类问题,以下两种方式都可以实现和
vm.items[indexOfItem] = newValue
相同的效果,同时也将在响应式系统内触发状态更新:// Vue.set Vue.set(vm.items, indexOfItem, newValue)
// Array.prototype.splice vm.items.splice(indexOfItem, 1, newValue)
你也可以使用
vm.$set
实例方法,该方法是全局方法Vue.set
的一个别名:vm.$set(vm.items, indexOfItem, newValue)
为了解决第二类问题,你可以使用
splice
vm.items.splice(newLength)
异步更新队列
可能你还没有注意到,Vue 在更新 DOM 时是异步执行的。只要侦听到数据变化,Vue 将开启一个队列,并缓冲在同一事件循环中发生的所有数据变更。如果同一个 watcher 被多次触发,只会被推入到队列中一次。这种在缓冲时去除重复数据对于避免不必要的计算和 DOM 操作是非常重要的。然后,在下一个的事件循环“tick”中,Vue 刷新队列并执行实际 (已去重的) 工作。Vue 在内部对异步队列尝试使用原生的
Promise.then
、MutationObserver
和setImmediate
,如果执行环境不支持,则会采用setTimeout(fn, 0)
代替。例如,当你设置
vm.someData = 'new value'
,该组件不会立即重新渲染。当刷新队列时,组件会在下一个事件循环“tick”中更新。多数情况我们不需要关心这个过程,但是如果你想基于更新后的 DOM 状态来做点什么,这就可能会有些棘手。虽然 Vue.js 通常鼓励开发人员使用“数据驱动”的方式思考,避免直接接触 DOM,但是有时我们必须要这么做。为了在数据变化之后等待 Vue 完成更新 DOM,可以在数据变化之后立即使用Vue.nextTick(callback)
。这样回调函数将在 DOM 更新完成后被调用。例如:<div id="example">{{message}}</div>
var vm = new Vue({ el: '#example', data: { message: '123' } }) vm.message = 'new message' // 更改数据 vm.$el.textContent === 'new message' // false Vue.nextTick(function () { vm.$el.textContent === 'new message' // true })
在组件内使用
vm.$nextTick()
实例方法特别方便,因为它不需要全局Vue
,并且回调函数中的this
将自动绑定到当前的 Vue 实例上:Vue.component('example', { template: '<span>{{ message }}</span>', data: function () { return { message: '未更新' } }, methods: { updateMessage: function () { this.message = '已更新' console.log(this.$el.textContent) // => '未更新' this.$nextTick(function () { console.log(this.$el.textContent) // => '已更新' }) } } })
因为
$nextTick()
返回一个Promise
对象,所以你可以使用新的 ES2017 async/await 语法完成相同的事情:methods: { updateMessage: async function () { this.message = '已更新' console.log(this.$el.textContent) // => '未更新' await this.$nextTick() console.log(this.$el.textContent) // => '已更新' } }
有时,我们想要显示一个数组经过过滤或排序后的版本,而不实际变更或重置原始数据。在这种情况下,可以创建一个计算属性,来返回过滤或排序后的数组。
<ul v-for="set in sets"> <li v-for="n in even(set)">{{ n }}</li> </ul>
data: { sets: [[ 1, 2, 3, 4, 5 ], [6, 7, 8, 9, 10]] }, methods: { even: function (numbers) { return numbers.filter(function (number) { return number % 2 === 0 }) } }
重复使用模板
v-for
也可以接受整数。在这种情况下,它会把模板重复对应次数。<div> <span v-for="n in 10">{{ n }} </span> </div>即重复使用div10次
v-for和template
类似于
v-if
,你也可以利用带有v-for
的来循环渲染一段包含多个元素的内容。
组件上使用v-for
任何数据都不会被自动传递到组件里,因为组件有自己独立的作用域。为了把迭代数据传递到组件里,我们要使用 prop
: