0. 看就完事了
参考阮总博客,还就那个轻松愉快 …
阮一峰 MVC,MVP和MVVM的图示
官方教程,多的不谈
VUE 深入响应式原理
官方API文档
内置的组件
Fundebug .cnblog 偶然看到的
详解Vue中的DOM
边城 .segmentfault 运气好才搜到的
揭密 Vue 的双向绑定
1.vm内置对象
1.1 computed
实现:相当于为该对象的protype声明了一个getter
执行:监听该属性的依赖属性是否变化
缓存:计算属性依赖于响应式依赖进行(像data那样的动态绑定)
1.2 watch
一个好的选择:通过监听状态来减少一个大函数的调用
执行:监听该属性是否变化
当需要侦听this.a.b时,需要这么写:‘a.b’
watch中使用箭头函数时候,this可能为undefined
如果侦听触发时不改变值,只是调用一个过程,可以直接a:‘methods中的方法名’
可选的内置属性:
handler:waitch的默认属性,类型是一个方法(val, oldVal)
deep:支持对对象内部属性的监听
immediate:watch开启时候的初始值赋值,也将触发一次
1.3 filter
实现:基于js原生的filter()方法
执行:每个渲染周期都会重新执行
模板渲染中支持管道符拼接多个filter
1.4 prop
声明时候,注意’-'和驼峰风格的使用
注意单向数据流 & js引用传递 的影响
prop属性中可以设置类型验证、默认、自定义验证函数
有了 inheritAttrs: false 和 $attrs,你就可以手动决定这些 attribute 会被赋予哪个元素
prop适合赋值子组件的初始值,但是该属性并不是只在初始化的生命周期中生效,具备data那样的动态绑定能力
子组件不能给自己的prop赋值,建议通过声明一个中间量(computed、data)
2. 指令
2.1 条件渲染
v-if 成立时渲染,不成立即销毁
v-show 初始化渲染,基于css的样式切换
v-for 拥有较高的渲染优先级
3.Vue内置函数
全局均可以引用(即Vue.xxx()),可简写作$xxx()
3.1 $el
找到dom元素
var data = { a: 1 }
var vm = new Vue({
el: '#example',
data: data
})
vm.$data === data // => true
vm.$el === document.getElementById('example') // => true
3.2 $set
vue实例对象(官网写作’vm’)创建之后添加新的属性到实例上,它不会触发视图更新,因此直接使用data.xxx = xxx的赋值方式,并且该属性getter/setter没有被声明时候,这将导致vue的v-vm绑定失败,因此这样修改之后是无法动态响应到view的
vue响应系统 ,把一个普通 Javascript 对象传给 Vue 实例来作为它的 data 选项,Vue 将遍历它的属性,用 Object.defineProperty 将它们转为 getter/setter,如上示例,可以将data在控制台打印出来看
new Vue({
data:(){
return {
queryParam:{}, //这么写,是一个空对象,该对象将自动声明存取器,但是内部属性未显式声明,将不具备存取器
//queryParam:{time:'',} //这么写,将自动具备存取器
},
};
},
mounted:function(){
this.queryParam.time = xxx; //这样是无法生效的,因为此时this.queryParam.time对象并没有getter/setter
this.$set(this.queryParam,'time',xxx);
},
});
3.3 $nextTick
当赋值数据时候,dom初始化完成。因此对未来(其实就是下一次异步更新队列的执行tick,可见update生命周期)更新后的视图进行操作可以使用这个
dom未初始化,常发生在vue生命周期钩子中
mounted()并不能保证所有的子组件全部完成挂载
new Vue({
...
mounted:function() {
get: function () {
this.$http.get('/api/article').then(function (res) {
this.list = res.data.data.list
// ref list 引用了ul元素,我想把第一个li颜色变为红色
this.$refs.list.getElementsByTagName('li')[0].style.color = 'red'
})
},
}
})
3.4 $forceUpdate
强制触发update生命周期,从而刷新视图、数据,
如果你发现你自己需要在 Vue 中做一次强制更新,99.9% 的情况,是你在某个地方做错了事。
当数据的层次过于复杂时候,可以使用$forceUpdate
3.5 $emit
触发对应事件名(建议使用kebab-case风格命名)的事件。
常用于组件间的事件传递:
子组件命名自定义事件名,并在底层组件(子组件的子组件)的事件回调中emit
父组件则将事件实现赋予(v-on)其子组件的自定义事件中
[实质是将自定义事件(底层事件的具体实现)作为底层事件的回调] //原谅这波拉跨的表达
类似的$on、$off、$once 就不谈了
3.6 $event
基于js原生的event内置对象,因此vue官方文档说可以用作触发子组件的原生dom事件。
对于event对象的用法,vue一样支持,懒得展开细说了。如需回炉重造,见阮总的js教程。
4.修饰符
组件prop属性的修饰符
4.1 sync
可以实现 看起来像父子组件“双向绑定” 一样的效果,建议子组件在computed中声明一个传递prop值的变量,并重写其get/set(get=>返回prop;set=>this.$emit(‘update:prop’,newValue)),这是“双向绑定”相对(相对于自定义v-model、emit()回调父类事件)优雅的一种实现
5.vm的一些内置属性的加载顺序
见源码:
function initState (vm) {
vm._watchers = [];
var opts = vm.$options;
if (opts.props) { initProps(vm, opts.props); }
if (opts.methods) { initMethods(vm, opts.methods); }
if (opts.data) {
initData(vm);
} else {
observe(vm._data = {}, true /* asRootData */);
}
if (opts.computed) { initComputed(vm, opts.computed); }
if (opts.watch && opts.watch !== nativeWatch) {
initWatch(vm, opts.watch);
}
}
6.响应式
6.1 组件内的响应式
当你把一个普通的 JavaScript 对象传入 Vue 实例作为 data 选项,Vue 将遍历此对象所有的 property,并使用 Object.defineProperty 把这些 property 全部转为 getter/setter。
6.2 组件间的响应式
每个组件实例都对应一个 watcher 实例,它会在组件渲染的过程中把“接触”过的数据 property 记录为依赖。之后当依赖项的 setter 触发时,会通知 watcher,从而使它关联的组件重新渲染。
6.3 特殊的响应式处理
由于 JavaScript 的限制,Vue 不能检测数组和对象的变化。尽管如此我们还是有一些办法来回避这些限制并保证它们的响应性。
对象->$set()
数组->slice()
通用、优雅,但是有失性能的深度监听
6.4 虚拟dom
Vue.js通过编译将template 模板转换成渲染函数(render ) ,执行渲染函数就可以得到一个虚拟节点树
在对 Model 进行操作的时候,会触发对应 Dep 中的 Watcher 对象。Watcher 对象会调用对应的 update 来修改视图。这个过程主要是将新旧虚拟节点进行差异对比,然后根据对比结果进行DOM操作来更新视图。
6.4.1 模板字符串的编译
官方推荐的(默认选项,runtime-only build),模板<template></template>在构建阶段被编译成js,因此打包阶段需要加入运行时的包即可(即官方文档的说法:编译器+运行时)
官方同时提供了完整版的包(编译+运行,compiler-included build),允许用户直接使用模板字符串在客户端(浏览器)直接生成dom并挂载在html标签中
这是vue 2.x 不同于vue 1.x的一点 => 不推荐走直接挂载dom => 建议走vnode(虚拟dom节点)方式
如果不嫌麻烦,也可以有替代方案 => vue.render(),使用该方法则不需要完整打包,compile the templates into render functions
6.5 vue建议数据驱动,而不是直接操作dom
这和目前主流所推崇的渲染方式是契合的,并不是vue一意孤行,angular、react都有这种异步的渲染操作。
6.5.1 就vue而言,直接操作dom带来的问题
结构上:破坏组件的封装性,在一个组件的代码中引用另一组件,增加了组件见的耦合
设计上:与vue的响应式相违背,vue的异步更新队列在watch到数据变动后,将开启一个队列缓冲一个tick内的数据变化、dom操作,并在下一个tick中执行。因此绕过数据来操作dom,很可能将导致不可预见的局面。
7.插槽
7.1 概述
插槽在渲染时将对应的模板代码合成为组件的一部分
可以提供一个默认的slot标签子节点作为默认的插槽内容
(后备内容)
父级模板里的所有内容都是在父级作用域中编译的;子模板里的所有内容都是在子作用域中编译的。
7.2 具名插槽
不带 name 的 <slot> 出口会带有隐含的名字“default”
7.2 作用域插槽
允许插槽的模板代码像props那样访问子组件
8.组件
8.1 内置组件
8.1.1 <component>
支持使用key、ref、is属性,甚至可以使用目标组件的prop予其赋值
9. vue devtools
浏览器的扩展商店里面搜索下载即可
可查看组件的属性值的变化