VueX
1. HTTP是无状态的,跨页面的数据无法共享,但Vue是单页面应用,VueX可以实现数据共享;
1. VueX的更新过程:Component --> Actions --> Mutations --> State --> Component
2. State:VueX管理的状态对象;
const state = { --> 该对象应该是唯一的
xxx: yyy ---> vuex管理的全局共享变量
}
3. Mutations:包含多个直接更新State方法的对象;
1. Action中的commit('Mutation的名称')触发更新;
2. Mutation中只能包含同步代码,不能有异步代码
4. Actions:包含多个事件回调函数的对象;
1. 执行commit()触发Mutation,间接更新state;
2. 在组件中,$store.dispatch('action的名称')触发回调;
3. Action中可以包含异步代码,如定时器、AJAX
使用VueX
1. npm/cnpm install --save vuex
2. 创建VueX的核心管理对象模块store.js
1. VueX是Vue的插件,需要先导入Vue:import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
2. 暴露Vuex.Store的四个常用的对象
const state = { count: 0 } --> 用于初始化状态
const getters = {
evOrOdd(state) { --> 不需要手动调用,只需要读取属性值
return state.count%2===0 ? '偶数' : '奇数'
}
}
const actions = {
increment({commit}, num) {
commit('INCREMENT', {num}) -->提交给mutations的INCREMENT()
}, ---> commit()传递的参数必须使用对象,参数为num
decrement({commit, state}) { --> 使用state,vuex内部的解构赋值
if(state.count === 10) return;
commit('DECREMENT') ---> 提交给mutations的DECREMENT()
},
asyncCrement({commit}) { ---> 在actions中执行异步逻辑
setTimeout(() => {
commit('DECREMENT')
}, 1000)
}
}
const mutations = {
INCREMENT(state, {num}) { -->实参为num,使用的解构赋值接收实参
state.count+=num ---> 操作全局共享的变量
},
DECREMENT(state) { state.count-- }
}
export default new Vuex.Store({
state, mutations, actions, getters-->包含多个getter计算属性的对象
})
3. 在main.js中引入Vuex模块:import store from './store'
new Vue({ ......,
store -->映射store,那么组件对象就具有一个指向store对象的属性:$store
})
4. 在vue组件中,使用store
computed: {
evOrOdd() { ---> 在计算属性中,获取store.count的属性值
return this.$store.getters.evOrOdd
}
}
methods: {
increment(num) { ---> dispatch()触发actions中的increment()
this.$store.dispatch('increment', num)
},
decrement() {
this.$store.dispatch('decrement')
},
}
5. 简写形式:import { mapState, mapActions, mapGetters } from 'vuex'
computed: { --> 计算vuex属性的简写形式
...mapState(['count']), ---> this.$store.state.count
...mapGetters(['evOrOdd']) -->this.$store.getters.evOrOdd()
}, ---> count和evOrOdd都映射为当前组件对象的属性
methods: { --> vuex:actions中的方法的简写形式
...mapActions(['increment', 'decrement', 'decrement'])
} ---> increment、decrement、decrement也都映射为methods中的方法
6. 如果actions、getters、mutations中的方法过多时,还可以拆分成一个个js模块;
7. watch也可以监听vueX中的数据变化
computed: { ---> 1.先使用计算属性返回vueX中的某个数据
count() {
this.$store.state.count
}
}
watch: { ---> 2.再使用watch监听
count: function(v1, v2) {
v1:新值,v2:旧值
}
}
Vue补充
1. render(h):渲染函数
new Vue({
el: '#app',
components: { App },
template: '',
})
简写形式:
new Vue({
el: '#app',
render: h => h(App),
})
2. this.$nextTick(callback):等待下一次事件轮询时执行,下一次Event Loop
1. 比如,v-html渲染html字符串是需要时间的,JS不能直接操作其中的DOM节点,需要等待下次
事件轮询;
data = 'HTML字符串'
this.$nextTick(()=>{
let test = document.getElementById('test');
})
2. $nextTick()与Vue钩子函数的实现原理是由浏览器的渲染机制决定的。
3. 便捷访问static目录下的图片:
4. 动态挂载组件
1. 创建Vue实例
let MyComponent = Vue.extend({
template: '{{uname}}
',
data: function(){
return { uname:'Mack' }
},
method: { ... }
})
2. 动态挂载到指定DOM节点上:
new MyComponent().$mount('#home'); ---> 方式一
new MyComponent({ el:'#home' }) ---> 方式二
3. 在文档之外渲染,随后再动态挂载
let component = new MyComponent().$mount()
document.getElementById('home').appendChild(component.$el)
实现原理
1. Vue作为一个MVVM框架的基本实现原理:数据代理、模板解析、数据绑定
2. Vue涉及的核心技术:虚拟DOM、Diff算法
3. 关键性方法:Object.defineProperty(obj, prop, descriptor)
DocumentFragment
1. DocumentFragment:文档碎片,虚拟DOM对象,表示一个没有父级文件的最小文档对象;
2. 被当作一个轻量版的Document使用,用于存储已排好版的或尚未打理好格式的XML片段;
3. Document对应显示的页面,包含N个Element,更新Document内部的元素,界面也会更新;
4. DocumentFragment并不是真实DOM树的一部分,而是内存中保存N个Element的容器对象,
不与界面关联,它的变化不会引起DOM树的重新渲染,界面不变,且不会导致性能等问题;
数据代理
1. 数据代理:通过一个对象代理操作另一个对象中的属性;
2. Vue的数据代理:通过vm对象来代理data对象中的所有属性操作;
3. Vue数据代理的实现:vm中的_data属性代理了data对象
1. 通过Object.defineProperty()给vm添加与data对象的属性对应的属性描述符,监视
vm的属性变化;
2. Object.defineProperty()会为vm中所有添加的属性提供getter/setter,它们内部
去操作data中对应的属性数据。
模板解析
1. 创建DocumentFragment对象,递归遍历DOM树,将DOM节点添加进DocumentFragment中,
也即,将DOM节点映射到虚拟DOM对象中;
2. 解析大括号表达式({{name}})、一般指令、事件指令。
数据绑定
1. 一旦更新了data对象中的某个属性数据,所有界面上直接/间接使用此属性的节点都会更新;
2. 数据劫持:Vue中用来实现数据绑定的一种技术;
3. 劫持的基本思想:也是通过Object.defineProperty()为data对象中的属性添加setter/
getter,来监视所有属性数据的变化,并随之更新界面;
4. vm --> data --> 更新界面
5. 双向数据绑定:建立在单向数据绑定的基础之上;
1. 在解析v-model指定时,给当前元素添加input监听;
2. 当input的value发生变化时,将最新的指赋给当前表达式对应的data对象中的属性。