emmmmm,,之前因为开项目来不及仔细读一遍,只能是用到什么找什么,然而深感对vue了解的无力(ŎдŎ;)。。还有一个周开新项目,恩,认真看一哈!( ̄▽ ̄)
【本文并没有讲解全部API,因为太多了。。总结了部分我觉得重要的点加以分析】
传送门:Vue.js中文API
Vue参考MVVM模式,使用vm (ViewModel 的简称)来表示Vue实例
vue是一个虚拟DOM的,以数据驱动为核心的前端框架。数据驱动也可以称为响应式系统,当属性的值发生变化时,视图都会“及时响应”,并更新相应的新值。
实例生命周期钩子函数
每个 Vue 实例在被创建之前,都要经过一系列的初始化过程,例如,Vue 实例需要设置数据观察(set up data observation)、编译模板(compile the template)、在 DOM 挂载实例(mount the instance to the DOM),以及在数据变化时更新 DOM(update the DOM when data change)。在这个过程中,Vue 实例还会调用执行一些生命周期钩子函数,这样用户能够在特定阶段添加自己的代码。
(图可能不是很清晰,小伙伴们可以参考原图)
- 对于数据的操作,比如props、data、computed的初始化都是在beforeCreate与created之间完成的,所以不了解的时候很可能会出现在别的钩子操作数据而产生奇奇怪怪的问题。
- 有一点要注意, 一般情况下vue组件总是会走完全部的生命周期的,即使你在created或者其他早期的生命周期钩子中使用了路由跳转或者location.herf重定向。
- 一些因生命周期问题而导致无法使页面刷新的问题有如下解决方案:
①this.nextTick({ })具体使用方法请移步传送门
②vuex
③setTimeout(code,millisec) 【可以强制推迟页面加载xx毫秒,强烈不推荐,暂缓之计,具体病因还是要具体解决】 - 生命周期钩子是一个很强大的功能,可以很好地处理挂载以及异步加载相关的事件,在特定阶段执行特定的代码,比如某几张图的出现顺序、比如axios请求数据来异步刷新等。
- 注意,任何生命周期钩子 中 this 上下文都会指向调用它的 Vue 实例。
关于生命周期具体理解推荐一篇文章来自segmentfault
3. 关于computed和watcher,留个flag,汇总一下再写
4. 修饰符(modifier)是以 . 表示的特殊后缀,表明应当以某种特殊方式绑定指令。
关于修饰符,请移步我的一篇搬运文章☞ Vue修饰符详解
5. 渲染
1. 根据条件进行渲染:v-if与v-show
-
v-if与v-show可以对内容进行灵活的选择性加载,是使用比较多的指令。
其二者的区别是,v-if是“真实”的条件渲染,因为它会确保条件块(conditional block)在切换的过程中,完整地销毁(destroy)和重新创建(re-create)条件块内的事件监听器和子组件。且v-if是惰性的(lazy),如果在初始渲染时条件为 false,它不会执行任何操作。直到在条件第一次变为 true 时,才开始渲染条件块。
相比之下,v-show 要简单得多 - 不管初始条件如何,元素始终渲染,并且只是基于 CSS 的切换。
通常来说,v-if 在切换时有更高的性能开销,而 v-show 在初始渲染时有更高的性能开销。因此,如果需要频繁切换,推荐使用 v-show,如果条件在运行时改变的可能性较少,推荐使用 v-if。
2. 列表渲染:v-for
- 在 v-for 代码块中,我们可以完全地访问父级作用域下的属性。v-for 还支持可选的第二个参数,作为当前项的索引:
<ul id="example-2">
<li v-for="(item, index) in items">
{{ parentMessage }} - {{ index }} - {{ item.message }}
</li>
</ul>
var example2 = new Vue({
el: '#example-2',
data: {
parentMessage: 'Parent',
items: [
{ message: 'Foo' },
{ message: 'Bar' }
]
}
})
结果:- 也可以使用 v-for 来遍历对象的属性,接着提供第二个参数,作为对象的键名(key),然后第三个参数作为索引(index):
<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
}
}
})
结果:注意,在遍历一个对象时,是按照 Object.keys() 得出 key 的枚举顺序来遍历,无法保证在所有 JavaScript 引擎实现中完全一致。
- 关于key,下列是API的原文
<div v-for="item in items" :key="item.id">
<!-- content -->
</div>
推荐在使用 v-for 时,尽可能提供一个 key,除非迭代的 DOM 内容足够简单,
或者你是故意依赖于默认行为来获得性能提升。
由于这是 Vue 识别节点的通用机制,因此 key 并不是仅限于与 v-for 关联,
我们将在之后的指南中看到,key 还可以其他场景使用。
因为没有用到过所以不是很理解,给个flag后续了解。
-
带有v-if的v-for
当它们都处于同一节点时,v-for 的优先级高于 v-if。这意味着,v-if 将分别在循环中的每次迭代上运行。当你只想将某些项渲染为节点时,这会非常有用,如下:
<li v-for="todo in todos" v-if="!todo.isComplete">
{{ todo }}
</li>
-
关于v-once
用法:<span v-once></span>
在API中给出的建议是性能优化,事实也确实如此,不过需要注意的是,用v-once
指令修饰的html内容在加载的时候会且只会加载一次
划重点!!!!
3. 数组变化检测(Array Change Detection)
Vue 将观察数组(observed array)的变化数组方法(mutation method)包裹起来,以便在调用这些方法时,也能够触发视图更新。这些包裹的方法如下:
push()
pop()
shift()
unshift()
splice()
sort()
reverse()
由于 JavaScript 的限制,Vue 无法检测到以下数组变动:
- 当你使用索引直接设置一项时,例如
vm.items[indexOfItem] = newValue
- 当你修改数组长度时,例如
vm.items.length = newLength
所以,使用Vue.set(example1.items, indexOfItem, newValue)
来解决第一个问题,
使用example1.items.splice(indexOfItem, 1, newValue)
来解决第一和第二个问题。
这两种方法可以通过响应式系统触发状态更新。
4. 对象变化检测(Array Change Detection)
受现代 Javascript 的限制, Vue 无法检测到对象属性的添加或删除:
var vm = new Vue({ data: { a: 1 } }) // `vm.a` 是响应的 vm.b = 2 // `vm.b` 不是响应的
Vue 不允许在已经创建的实例上,动态地添加新的根级响应式属性(root-level reactive property)。然而,可以使用 Vue.set(object, key, value) 方法,将响应式属性添加到嵌套的对象上。例如:
var vm = new Vue({ data: { userProfile: { name: 'Anika' } }})
可以向嵌套的 userProfile 对象,添加一个新的 age 属性:
Vue.set(vm.userProfile, 'age', 27)
还可以使用 vm.$set 实例方法,这也是全局 Vue.set 方法的别名:
vm.$set(this.userProfile, 'age', 27)
这是刚接触Vue的时候踩到过的一个大坑,现在想起来还头皮发麻
∑(゚Д゚ノ)ノ
6. DOM 模板解析
当时用DOM模板时,会受到一些来源于HTML的限制,比如,这种写法是报错的:
<table>
<!--my-row是自定义模板-->
<my-row>...</my-row>
</table>
解决方案:
<table>
<tr is="my-row"></tr>
</table>
is
属性请自行百度。
敲黑板
在使用以下字符串模板之一的场景中,这些限制将不再适用:
- <script type="text/x-template">
- JavaScript 内联模板字符串
- .vue 组件
所以,用.vue吧,毕竟用的就是vue框架233333_(:з」∠)_
7. 组件复用
组件(component)是 Vue 最强大的功能之一。组件可以帮助你扩展基本的 HTML 元素,以封装可重用代码。
在编写组件时,记住是否要复用组件有好处。一次性组件跟其它组件紧密耦合没关系,但是可复用组件应当定义一个清晰的公开接口。
Vue 组件的 API 来自三部分 - props, events 和 slots :
- Props 允许外部环境传递数据给组件
- Events 允许组件对外部环境产生副作用(side effects)
- Slots 允许外部环境将额外的内容组合在组件中。
8. 组件的组合与通信
组件,意味着组合在一起使用的元件,多数场景是父子关系:组件 A 可以在自己的模板中使用组件 B。这就必然的需要彼此相互通信:父组件可能会向下传递数组给子组件,然后子组件也可能会将自身发生的变化通知到父组件。然而,重要的是,为了尽可能将父子组件解耦,需要有一个定义清晰的接口。定义清晰的通信方式,可以确保组件可以相对隔离地组织代码,以及合乎逻辑易于推断,从而使它们更加易于维护,并且可能更加易于复用。
vue的大方面的功能核心就是组件,正是组件的组合嵌套复用构成了快速且多样的vue项目生态圈,而组件通信又是组件中比较重要的知识点。
-
父向子组件:
- 在子组件中添加props(既可以传递数据也可以传递方法)
常用形式<child :msg = "parentMsg"/>
含有路由出口的使用形式<router-view :propsdata="data"/> - this.$broadcast 调用子组件方法(子组件在events中写被调用方法)
- 父组件通过this.$ref获得子组件的引用
【$refs 只在组件渲染完成后才填充,并且它是非响应式的。它仅仅作为一个直接访问子组件的应急方案 - 应当避免在模板或计算属性中使用 $refs。】 - 使用this.$children()获得子组件的Vue实例
- 在子组件中添加props(既可以传递数据也可以传递方法)
-
子向父组件:
- this.$emit (父组件在methods中写被调用方法,并通过@event绑定到子组件) ,子组件中通过这种方法传递数给父组件同时激活父组件的被调用方法。
- this.$dispath (父组件在events中写被调用方法)
- 在子组件中添加插槽slot,父组件可以向子组件中插入模板 <template/> ,通过slot-scope获得子组件返回的值
- 使用this.$parent获得父组件Vue实例 (this.$root获得根组件的Vue实例)
一点补充:在某些场景中,我们可能需要对一个 prop 进行「双向绑定」 - 事实上,这个功能在 Vue 1.x 中已经由
.sync
修饰符实现。但是在2.0中移除,在2.3.0+中以语法糖的形式再次加入。虽然用的不多,如果想了解请移步API。
- 通过bus.js或者自身的vue实例来进行不同组件之间的数据传递
- 通过new一个Vue对象作为通信的桥梁(bus.$emit() => bus.$on())
- 自身的vue实例(this.$emit() => this.$on())
- Flux以及Vuex(全局单例模式)同时也可用于解决不同组件之间的通信问题(解决了繁杂事件订阅和广播)
- 路由传参
这里要注意,第一种方式是无法传参的,要传参必须通过第二种方式,即以name
的形式而不能以路径的形式。所以在路由中的定义如下第三张图。
关于slot,与props相似,简单来说就是props把数据扔到子组件中,slot把html扔到子组件中。关于slot留个flag后续写个专栏具体补充。。。
请注意,props是单向数据流,按照自上而下单向流动方式构成
9. 动态组件
- 简单来说,与v-bind动态选择css一个样子,根据父组件给的变量决定显示哪个组件,或者都不显示。
- 使用方式:
<component v-bind:is="组件名"></component>
- 有一点需要注意,像v-if一样,动态加载组件是需要重渲染的,所以如果想避免重新渲染可以添加keep-alive属性来保持已渲染的组件不被移除。
<component v-bind:is="组件名" keep-alive></component>
- activate延迟加载
activate是和data等属性平级的一个属性,形式是一个函数,函数里默认有一个参数,而这个参数是一个函数。
如下实例:
data(){
return{
//...
}
},
activate (done) { //执行这个参数时,才会切换组件
var self = this;
//
axios.get("/test", function (data) {
self.hello = data;
done(); //ajax执行成功,切换组件
})
}
注意:
【1】只有在第一次渲染组件时,才会执行activate,且该函数只会执行一次(在第一次组件出现的时候延迟组件出现)
【2】没有keep-alive时,每次切换组件出现都是重新渲染(因为之前隐藏时执行了destroy过程),因此会执行activate方法。
10. 组件杂项
以下全部有待补充,惯例,flaggggggggggggg
- 异步组件/代码分离
应用做大了以后可以进行性能优化,后续详细补充 - 命名规范
- 组件之间的循环引用
- 组件库
- 其他
11. 过渡&动画
概述
过渡和动画可以对页面内容以及用户体验做一些良好的提升,避免生硬的切换效果带来的挫顿感。个人看法:如果不考虑模块化发布或者工程量不是很大,在系统功能完善之后进行过度动画的添加可以对页面逼格进行大幅提升~
从页面中添加(显示)、移除(隐藏)或者更新一些成员的时候,Vue提供了多种的过渡动画来避免生硬的元素转变。包括以下工具:
- 在 CSS 过渡和动画中自动处理 class
- 可以配合使用第三方 CSS 动画库,如 Animate.css
- 在过渡钩子函数中使用 JavaScript 直接操作 DOM
- 可以配合使用第三方 JavaScript 动画库,如 Velocity.js
单元素/组件的过渡
Vue提供了transition
外层包裹容器组件(wrapper component),可以给下列情形中的任何元素和组件添加进入/离开(enter/leave)过渡:
- 条件渲染(使用 v-if)
- 条件展示(使用 v-show)
- 动态组件
- 组件根节点
一个demo:
<template>
<div id="demo">
<button v-on:click="show = !show">
Toggle
</button>
<transition name="fade">
<p v-if="show">hello</p>
</transition>
</div>
</template>
<script>
new Vue({
el: '#demo',
data: {
show: true
}
})
</script>
<style>
.fade-enter-active, .fade-leave-active {
transition: opacity .5s;
}
.fade-enter, .fade-leave-to /* .fade-leave-active 在低于版本 2.1.8 中 */ {
opacity: 0;
}
</style>