Vue.use()方法
首先使用vue的插件,例如vue-router/vuex都要在引入后执行Vue.use(Xxx)如果传入的Xxx是个函数,就会直接调用这个函数并传入Vue这个类,如果是对象就直接调用里面的install方法并传入Vue这个类
代码
使用的时候引入Vuex然后Vue.use(Vuex),但是还有之后的new Vue.store({})就说明引入的Vuex是个对象,有个install方法,有个Store类,在install方法中为每一个组件添加一个$store属性指向Store实例,利用全局混入,为每个组件设计beforeCreate钩子函数,函数中的this指向当前组件
let Vue=null
function install(_Vue){
Vue=_Vue
//为每个组件添加$store
Vue.minix({
beforeCreate(){
if(this.$options.store){
this.$store=this.$options.store
}else if(this.$parent){
this.$store=this.$parent.$store
}
}
})
}
class Store{
constructor(options){
//new Vue.Store({})传入的options中可能没有mutations/actions/getters
//就把相应的mutations/actions/getters设为{}
let {state,mutations,actions,getters}=options
let vm=new Vue({
data:{
state
}
})
this.state=vm.state
this.mutations=mutations||{}
this.actions=actions||{}
//虽然在new Store传入的getters对象中是函数,但是它相当于computed
//使用时this.$store.getters.xxx,得到xxx方法的结果,所以在store实例上添加的getters是一个对象,属性名是传入的函数名,属性值是函数执行之后的值,因为他会随着state值得变化而改变值所以就要把getters对象中得属性通过Object.defineProperty(this.getters,xxx,{get=()=>{}})当state中数据改变就要重新渲染页面重新计算getters中得值
this.getters={}
let newGet=getters||{}
Object.keys(newGet).forEach(item=>{
//为this.getters添加属性
Object.defineProperty(this.getters,item,{
get=()=>{
return newGet[item].call(this,this.state)
}
})
}
}
commit(type,only1){
this.mutations[type]&&this.mutations[type].call(this,this.state,only1)
}
dispatch(type,only1){
this.actions[type]&&this.actions[type].call(this,this,only1)
}
}
let Vuex={
install,
Store
}
export default Vuex
//正常使用vuex的内容要this.$store.state.yyy或this.$store.commit("type",parmas)
//这样是很麻烦的,于是就有了从文件中导入mapSate方法,传入一个数组或对象,把用到的state,放到数组中传给mapState方法
export function mapState(ary){
let obj={}
if(Array.isArray(ary)){
ary.forEach(item=>{
obj[item]=function(){
return this.$store.state[item]
}
})
}else if(Object.prototype.toString.call(ary)==="[object Object]"){
Object.keys(ary).forEach(item=>{
obj[item]=function(){
return this.$store.state[ary[item]]
}
})
}
return obj
}
export function mapMutations(ary){
let obj={}
ary.forEach(item=>{
obj[item]=function(params){
this.$store.commit(item,params)
}
})
return obj
}
export function mapActions(ary){
let obj={}
ary.forEach(item=>{
obj[item]=function(params){
this.$store.dispatch(item,params)
}
})
return obj
}
export function mapGetters(ary){
let obj={}
ary.forEach(item=>{
obj[item]=function(){
return this.$store.getters[item]
}
})
return obj
}
总结
先从Vuex的使用说起,先引入Vuex,使用Vue.use(Vuex),然后再new Vuex.Store(options),options是vuex中的状态(state),mutaions/actions/getters,之后把创造的store实例暴露出去,在new Vue的根组件的options中挂载这个store实例,首先Vue.use(Vuex),是把引入的Vuex对象中的install方法执行并传入Vue,在这里利用全局混入为每个组件添加beforeCreate钩子函数,并在钩子函数中为当前组件添加$store,这个属性的属性值就是挂载的那个store实例,在Store类中,constructor中设定好state,通过new Vue()实现传入的state的相应式,把mutations和actions赋值好,向原型中添加commit和dispatch方法