vue的生命周期
*************************************************
每个组件或者实例都经历的生命周期:初始化、运行中和销毁。
1.实例或者组件通过new Vue()创建初始化事件和生命周期,然后执行beforeCreate(数据还未挂载,一个空壳,无法访问数据和DOm)
2.挂载数据、绑定事件,然后执行create函数(可以进行倒数第二次更改数据,不触发其他钩子函数,可以做初始化数据获取)
3.查找实例或者组件中对应的模板准备渲染,然后执行beforeMount(虚拟DOM已经完成,准备渲染,可以进行倒数第一次更改数据,可以做初始化数据的获取)
4.开始render渲染真实的dom,然后执行mounted钩子函数(组件、数据、dom、事件都已挂载好,可以进行dom操作)
5.当组件或实例的数据更改,执行beforeUpdate,vue的虚拟dom机制会重新构建虚拟dom树利用diff算法(同层比较)对比后重新渲染
6.当更新后执行updated,可以重新进行dom操作
7.当调用$destory方法后,执行beforeDestory(善后操作:清除计时器、非指令绑定的事件)
8.组件的数据绑定、监听去除 只剩下dom空壳,执行destoryed(也可做善后)
*************************************************
***************************************
父子组件传值
父组件向子组件传值成功
总结一下:
子组件在props中创建一个属性,用以接收父组件传过来的值
父组件中注册子组件
在子组件标签中添加子组件props中创建的属性
把需要传给子组件的值赋给该属性
子组件向父组件传值成功
总结一下:
子组件中需要以某种方式例如点击事件的方法来触发一个自定义事件
将需要传的值作为$emit的第二个参数,该值将作为实参传给响应自定义事件的方法
在父组件中注册子组件并在子组件标签上绑定对自定义事件的监听
兄弟组件传值
1、兄弟之间传递数据需要借助于事件车,通过事件车的方式传递数据
2、创建一个Vue的实例,让各个兄弟共用同一个事件机制。
3、传递数据方,通过一个事件触发bus.$emit(方法名,传递的数据)。
4、接收数据方,通过mounted(){}触发bus.$on(方法名,function(接收数据的参数){用该组件的数据接收传递过来的数据}),
此时函数中的this已经发生了改变,可以使用箭头函数。
实例如下:
我们可以创建一个单独的js文件eventVue.js,内容如下
import Vue from 'vue'
export default new Vue
***************************************
vuex
状态管理模式,组件的状态管理,中央管理处
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex);
export default new Vuex.Store({
state: {
//存放组件之间共享的数据
count: 0,
name: "天才"
},
mutations: {
//显示的更改state中的数据
// increment: state => state.count++,
increment: (state, value) => state.count += value,
decrement: state => state.count--,
},
getters: {
//过滤stat中的数据
getAge: function(state) {
return state.name;
}
},
actions: {
/***
* context:context是与 store 实例具有相同方法和属性的对象。
可以通过context.state和context.getters来获取 state 和 getters。
* dispatch:翻译为‘派发、派遣’的意思,触发事件时,dispatch就会通知actions(跟commit一样一样的)参数跟commit也是一样的。
incrementAction: function(context, data) {}
*
*
*/
incrementAction: function(context, value) {
setTimeout(function() {
context.commit('increment', value);
}, 1000);
}
}
})
// this.$store.commit("increment")
this.$store.dispatch("incrementAction", 10);
*************************************************
MVVM的实现
*************************************************
订阅者模式(backbone.js)是 vm.set('property', value)
脏值检查(angular.js)比对数据是否有变更,来决定是否更新视图
数据劫持(vue.js)采用数据劫持结合发布者-订阅者模式的方式,
通过Object.defineProperty()来劫持各个属性的setter,getter,
在数据变动时发布消息给订阅者,触发相应的监听回调
1.实现一个数据监听器Observer,能够对数据对象的所有属性进行监听,如有变动可拿到最新值并通知订阅者
2.实现一个指令解析器Compile,对每个元素的节点的指令进行扫描和解析,根据指令模板替换数据,一级绑定相应的跟新函数
3.实现一个Watcher,作为连接Observer和Compile的桥梁,
能订阅并收到每个属性变动的通知,执行指令绑定的相应的回调函数,从而跟新视图
(监听数据对象的属性变化(Observer数据监听器)和元素节点的变化(Compile指令解析器)执行相应的回调函数跟新视图(Watcher)
*************************************************
vue-router
*************************************************
导航守卫
全局前置守卫
router.beforeEach((to, from, next) => {
// ...
})
全局解析守卫(前置守卫类似)
router.beforeResolve((to, from, next) => {
// 在所有组件内守卫和异步路由组件被解析之后被调用
})
全局后置钩子(相比前置少了个next)
router.afterEach((to, from) => {
// ...
})
全局独享守卫(单个路由使用)
beforeEnter: (to, from, next) => {
// ...
}
组件内的守卫
const Foo = {
template: `...`,
beforeRouteEnter (to, from, next) {
// 在渲染该组件的对应路由被 confirm 前调用
// 不!能!获取组件实例 `this`
// 因为当守卫执行前,组件实例还没被创建
next(vm => {
// 通过 传一个回调`vm` 给next访问组件实例
})
},
beforeRouteUpdate (to, from, next) {
// 在当前路由改变,但是该组件被复用时调用
// 举例来说,对于一个带有动态参数的路径 /foo/:id,在 /foo/1 和 /foo/2 之间跳转的时候,
// 由于会渲染同样的 Foo 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。
// 可以访问组件实例 `this`
},
beforeRouteLeave (to, from, next) {
// 导航离开该组件的对应路由时调用
// 可以访问组件实例 `this`
const answer = window.confirm('Do you really want to leave? you have unsaved changes!')
if (answer) {
next()
} else {
next(false)
}
}
}
***********************************
指令
************************************
v-slot:
在组建中添加内容
提升用户体验:v-cloak
防止刷新页面,网速慢的情况下出现{{ message }}等数据格式
提升性能:v-pre
跳过这个元素和它的子元素的编译过程。跳过大量没有指令的节点会加快编译。
提升性能:v-once
只渲染元素和组件一次。随后的重新渲染,元素/组件及其所有的子节点将被视为静态内容并跳过。
# 1. Vue.js是什么?
1). 一位华裔前Google工程师(尤雨溪)开发的前端js库
2). 作用: 动态构建用户界面
3). 特点:
* 遵循MVVM模式
* 编码简洁, 体积小, 运行效率高, 移动/PC端开发
* 它本身只关注UI, 可以轻松引入vue插件和其它第三库开发项目
4). 与其它框架的关联:
* 借鉴angular的模板和数据绑定技术
* 借鉴react的组件化和虚拟DOM技术
5). vue包含一系列的扩展插件(库):
* vue-cli: vue脚手架
* vue-resource(axios): ajax请求
* vue-router: 路由
* vuex: 状态管理
* vue-lazyload: 图片懒加载
* vue-scroller: 页面滑动相关
* mint-ui: 基于vue的组件库(移动端)
* element-ui: 基于vue的组件库(PC端)
# 2. 基本使用
1). 引入vue.js
2). 创建Vue实例对象(vm), 指定选项(配置)对象
el : 指定dom标签容器的选择器
data : 指定初始化状态数据的对象/函数(返回一个对象)
3). 在页面模板中使用{{}}或vue指令
# 3. Vue对象的选项
## 1). el
指定dom标签容器的选择器
Vue就会管理对应的标签及其子标签
## 2). data
对象或函数类型
指定初始化状态属性数据的对象
vm也会自动拥有data中所有属性
页面中可以直接访问使用
数据代理: 由vm对象来代理对data中所有属性的操作(读/写)
## 3). methods
包含多个方法的对象
供页面中的事件指令来绑定回调
回调函数默认有event参数, 但也可以指定自己的参数
所有的方法由vue对象来调用, 访问data中的属性直接使用this.xxx
## 4). computed
包含多个方法的对象
对状态属性进行计算返回一个新的数据, 供页面获取显示
一般情况下是相当于是一个只读的属性
利用set/get方法来实现属性数据的计算读取, 同时监视属性数据的变化
如何给对象定义get/set属性
在创建对象时指定: get name () {return xxx} / set name (value) {}
对象创建之后指定: Object.defineProperty(obj, age, {get(){}, set(value){}})
## 5). watch
包含多个属性监视的对象
分为一般监视和深度监视
xxx: function(value){}
xxx : {
deep : true,
handler : fun(value)
}
另一种添加监视方式: vm.$watch('xxx', function(value){})
# 4. 过渡动画
利用vue去操控css的transition/animation动画
模板: 使用<transition name='xxx'>包含带动画的标签
css样式
.fade-enter-active: 进入过程, 指定进入的transition
.fade-leave-active: 离开过程, 指定离开的transition
.xxx-enter, .xxx-leave-to: 指定隐藏的样式
编码例子
.xxx-enter-active, .xxx-leave-active {
transition: opacity .5s
}
.xxx-enter, .xxx-leave-to {
opacity: 0
}
<transition name="xxx">
<p v-if="show">hello</p>
</transition>
# 5. 生命周期
vm/组件对象
生命周期图
主要的生命周期函数(钩子)
created() / mounted(): 启动异步任务(启动定时器,发送ajax请求, 绑定监听)
beforeDestroy(): 做一些收尾的工作
# 6. 自定义过滤器
## 1). 理解
对需要显示的数据进行格式化后再显示
## 2). 编码
1). 定义过滤器
Vue.filter(filterName, function(value[,arg1,arg2,...]){
// 进行一定的数据处理
return newValue
})
2). 使用过滤器
<div>{{myData | filterName}}</div>
<div>{{myData | filterName(arg)}}</div>
# 7. vue内置指令
v-text/v-html: 指定标签体
* v-text : 当作纯文本
* v-html : 将value作为html标签来解析
v-if v-else v-show: 显示/隐藏元素
* v-if : 如果vlaue为true, 当前标签会输出在页面中
* v-else : 与v-if一起使用, 如果value为false, 将当前标签输出到页面中
* v-show: 就会在标签中添加display样式, 如果vlaue为true, display=block, 否则是none
v-for : 遍历
* 遍历数组 : v-for="(person, index) in persons"
* 遍历对象 : v-for="value in person" $key
v-on : 绑定事件监听
* v-on:事件名, 可以缩写为: @事件名
* 监视具体的按键: @keyup.keyCode @keyup.enter
* 停止事件的冒泡和阻止事件默认行为: @click.stop @click.prevent
* 隐含对象: $event
v-bind : 强制绑定解析表达式
* html标签属性是不支持表达式的, 就可以使用v-bind
* 可以缩写为: :id='name'
* :class
* :class="a"
* :class="{classA : isA, classB : isB}"
* :class="[classA, classB]"
* :style
:style="{color : color}"
v-model
* 双向数据绑定
* 自动收集用户输入数据
ref : 标识某个标签
* ref='xxx'
* 读取得到标签对象: this.$refs.xxx
# 8. 自定义指令
## 1). 注册全局指令
Vue.directive('my-directive', function(el, binding){
el.innerHTML = binding.value.toUpperCase()
})
## 2). 注册局部指令
directives : {
'my-directive' : function(el, binding) {
el.innerHTML = binding.value.toUpperCase()
}
}
## 3). 使用指令
<div v-my-directive='xxx'>