1.Vue中数据双向绑定的实现原理
首先我们要知道什么是数据的双向绑定
双向绑定也就是我们平时所说的MVVM模式,即model,view,view-model
假如你在js中定义了一个对象
var cat = {
name: 'Tom'
}
假定我们通过某种方法使整个对象的数据和某个DOM节点关联起来,以达到以下目的:
修改DOM节点的数据可以改变cat对象的数据,
修改cat对象的数据可以改变DOM节点的数据。
这便是我们所说的MVVM模式
搞清楚什么是双向绑定后,现在来说说Vue中的实现方式
vue.js 采用数据劫持结合发布者-订阅者模式的方式,通过Object.defineProperty()来劫持各个属性的setter,getter,在数据变动时发布消息给订阅者,触发相应的监听回调。
这句话一时也许很难理解
首先在Vue中什么是数据劫持,它就是通过Object.defineProperty()来获取属性的getter和setter方法,来进行数据的监控
其次什么是发布者-订阅者模式,它有另一个更为熟悉的模式,即观察者模式,这是一种javascript的设计模式。用通俗的话来讲,它就像是微信公众号和订阅者的关系,作为订阅者的你不必每天去请求公众号给你发信息。
接下来就来看看它的实现原理了
上图中,new MVVM()便是我们最终需要的,它的实现主要通过Observer,Compile,Watcher。
1.Observer使用Object.defineProperty()对数据对象的所有属性进行监听,如有变动可拿到最新值并通知订阅者;
2.Compile是一个解析器,其目的就是渲染视图。它通过解析模板指令,将模板中的变量替换成数据,然后初始化渲染页面视图,并将每个指令对应的节点绑定更新函数,添加监听数据的订阅者,一旦数据有变动,收到通知,更新视图
3.Watcher便是这里的订阅者,作为连接Observer和Compile的桥梁,能够订阅并收到每个属性变动的通知,执行指令绑定的相应回调函数,从而更新视图
以上便是Vue的双向绑定实现原理
2.Vuex
什么是Vuex?
简单来说,Vuex是专门设计为Vue进行状态管理的模式
Vuex在项目中的应用
首先初始化一个vue项目,并通过以下指令安装vuex依赖:
npm install vuex -s
之后在项目的src目录下新建一个store文件夹,形成以下文件结构:
下面讲解以下以上文件的作用:
state
state中储存数据的状态,也就是你需要管理的数据保存在state中
// state保存数据的状态
const state = {
val: {
count: 0,
type: Number
}
}
export default state
getter
getter相当于store的computed属性,对数据进行加工过滤
export const count = (state) => {
return state.val.count
}
export const type = (state) => {
return state.val.type
}
这里便是将val的count和type剥离了出来
mutation-type
mutation-type并不是vuex的核心概念,它是一种mutation的规范,定义mutation的函数名
export const ADD = 'ADD'
mutation
在vuex中,改变数据状态的唯一方式就是提交mutation;
mutation获取state中数据的状态,并对其进行操作,需要注意的是mutation中进行的都是同步操作
import * as types from './mutation-type.js'
export default {
[types.ADD] (state) {
state.val.count += 1
}
}
actions
action和mutation的作用相同,但区别在于action中进行的是异步操作,或者多个commit
import * as types from './mutation-type.js'
export default {
addAction ({commit}) {
setTimeout(() => {
commit(types.ADD)
}, 1000)
console.log('异步执行的actions')
}
}
以上是提交一个add的mutation,commit是进行提交必要的参数,这里使用setTimeout是为了体现异步执行
store
store便是装配以上内容后对外导出的接口了,通常将装配写在store下的index.js中
import vue from 'vue'
import vuex from 'vuex'
import state from './state.js'
import * as getters from './getters.js'
import mutations from './mutations.js'
import actions from './actions.js'
import m1 from './modules/m1.js'
import m2 from './modules/m2.js'
vue.use(vuex)
export default new vuex.Store({
state,
getters,
mutations,
actions,
modules: {
m1,
m2
}
})
这里的model之后再进行解释
在组件中使用
有以下四个方法:
mapstate 获取state数据
mapgetters 获取getters数据
mapMutations 调用mutations方法
mapActions 调用actions方法
{{count}}
{{count}
import { mapState, mapGetters, mapMutations, mapActions } from 'vuex'
computed: {
// 获取state中的数据
// ...mapState(['count'])
...mapGetters(['count'])
},
methods: {
...mapMutations({
'add': 'ADD'
}),
...mapActions({
'addAction': 'addAction'
})
}
上述4种函数调用的时候可以使用扩展运算符...直接调用
获取数据的方式可以是
...mapState(['count'])//当state中的count和组件中的count名相同时
...mapState({'count': 'icount')当state中数据和组件中不同名时,这里是icount
由于state中的数据是嵌套对象,所以使用mapGetters来获取count
module
当组件数量增多时,其状态也会变多,此时所有的状态在同一个store中便会很复杂。
这时就可以创建不同的module,使用不同或相同的state,getters,mutations,actions ,使结构更加清晰