每个组件都共享Store中的数据, 以及每个组件都可以通过 $store.state 或者 getters 拿到传入的数据,
通过事件 或者 回调函数 触发 muation,进行同步更新数据, 从而触发视图更新
通过 提交 action 进行异步操作数据,
main.js
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store/index'
Vue.config.productionTip = false
new Vue({
router,
store,
render: h => h(App)
}).$mount('#app')
src/store/index.js
import Vue from 'vue'
import Vuex from 'vuex'
// 使用 了 Vue.use() 方法,官方文档是这样解释的, 可以看到使用 use() 方法,必须提供一个 install 方法
// 该方法 有两个 参数, 一个 是 Vue 的构造器, 另一个是可选项
Vue.use(Vuex)
export default new Vuex.Store({
state: {
num:0,
name:'我是测试数据',
mill: "我是getters用的"
},
getters:{
getMill(state) {
return state.mill
}
},
mutations: {
incr(state, payload){
state.num += payload
},
desr(state, payload){
state.num -= payload
}
},
actions: {
asyncIncr({commit}, payload){
setTimeout( () => {
commit('incr', payload)
}, 0)
}
},
modules: {
}
})
App.vue
<template>
<div id="app">
<h2>vuex</h2>
<p>{{$store.state.name}}</p>
<p>{{$store.getters.getMill}}</p>
{{$store.state.num}}
<button @click="addNum">点击加1</button>
<button @click="AnsyncIncr">异步加一</button>
</div>
</template>
<script>
export default {
mounted() {
// setInterval(() => {
// this.$store.state.num += 1
// }, 1000)
},
methods:{
addNum(){
this.$store.commit('incr',1)
},
AnsyncIncr(){
this.$store.dispatch('asyncIncr', 2)
}
}
}
</script>
<style lang="less">
#app {
font-family: 'Avenir', Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
}
#nav {
padding: 30px;
a {
font-weight: bold;
color: #2c3e50;
&.router-link-exact-active {
color: #42b983;
}
}
}
</style>
const install = _Vue => {
console.log("install")
}
export default {
install
}
let Vue
class Store {}
const install = _Vue => {
console.log("install")
Vue = _Vue // 用一个变量接收 _Vue 构造器
// 全局注册一个混入,影响注册之后所有创建的每个 Vue 实例
Vue.mixin({
beforeCreate() {
console.log(1)
}
})
}
export default {
install,
Store
}
由于数据是共享的,每个组件都需要拿到store数据,在使用时通过this. s t o r e 拿 到 , 也 就 是 每 个 组 件 都 需 要 有 store拿到,也就是每个组件都需要有 store拿到,也就是每个组件都需要有store属性,可以通过$options拿到所有的属性,结果如下:
let Vue
class Store {}
const install = _Vue => {
console.log("install")
Vue = _Vue // 用一个变量接收 _Vue 构造器
Vue.mixin({
beforeCreate() {
console.log(this.$options)
}
})
}
export default {
install,
Store
}
let Vue
class Store {}
const install = _Vue => {
console.log("install")
Vue = _Vue // 用一个变量接收 _Vue 构造器
Vue.mixin({
beforeCreate() {
//判断 根 实例 有木有传入store 数据源,
//如果传入了, 就把它放到实例的 $store上
if (this.$options && this.$options.store) {
this.$store = this.$options.store
} else {
// 2. 子组件去取父级组件的$store属性
this.$store = this.$parent && this.$parent.$store
}
}
})
}
export default {
install,
Store
}
let Vue
class Store {
constructor(options = {}) {
console.log(options)
}
}
const install = _Vue => {
console.log("install")
Vue = _Vue // 用一个变量接收 _Vue 构造器
Vue.mixin({
beforeCreate() {
//判断 根 实例 有木有传入store 数据源,
//如果传入了, 就把它放到实例的 $store上
if (this.$options && this.$options.store) {
this.$store = this.$options.store
} else {
// 2. 子组件去取父级组件的$store属性
this.$store = this.$parent && this.$parent.$store
}
}
})
}
export default {
install,
Store
}
class Store {
constructor(options = {}) {
this.state = options.state
}
}
App.vue
<template>
<div id="app">
<h2>vuex</h2>
<p>{{$store.state.name}}</p>
</div>
</template>
<script>
export default {}
</script>
import Vue from "vue"
import Vuex from "vuex"
Vue.use(Vuex)
export default new Vuex.Store({
state: {
name: "我是原生的state数据",
mill: "我是getters用的"
},
getters: {
getMill(state) {
return state.mill
}
},
mutations: {},
actions: {},
modules: {}
})
App.vue
<template>
<div id="app">
<h2>vuex</h2>
<p>{{mill}}</p>
</div>
</template>
<script>
export default {
computed: {
mill() {
return this.$store.getters.getMill
}
}
}
</script>
class Store {
constructor(options = {}) {
this.state = options.state
// 定义实例上的 getters
this.getters = {}
// 遍历所有的对象中的方法名
Object.keys(options.getters).forEach(key => {
// 重新构造 this.getters 对象
Object.defineProperty(this.getters, key, {
get: () => {
return options.getters[key](this.state)
}
})
})
}
}
现在基本上实现了state,getters,但是会有一个问题,直接改 vuex 的数据是可以变化的,但是现在无法改变
错误演示:
App.vue
<template>
<div id="app">
<h2>vuex</h2>
<p>{{mill}}</p>
<p>{{$store.state.num}}</p>
</div>
</template>
<script>
export default {
computed: {
mill() {
console.log(this.$store.getters)
return this.$store.getters.getMill
}
},
mounted() {
setInterval(() => {
this.$store.state.num += 1
}, 1000)
}
}
</script>
index.js
import Vue from "vue"
import Vuex from "./myStore"
Vue.use(Vuex)
export default new Vuex.Store({
state: {
name: "我是原生的state数据",
mill: "我是getters用的",
num: 1
},
getters: {
getMill(state) {
return state.mill
}
},
mutations: {},
actions: {},
modules: {}
})
然而使用 我们自己写的 发现确不变化, 那么需要来解决这个问题
我们知道 ,vue 中的数据只要是写在 data 中的,都是支持 响应式的, 所以 我们只有把 vuex 中的state 定义在 Vue中的 data中
改写代码:
class Store {
constructor(options = {}) {
this.state = new Vue({
data() {
return {
state: options.state
}
}
})
// 定义实例上的 getters
this.getters = {}
// 遍历所有的对象中的方法名
Object.keys(options.getters).forEach(key => {
// 重新构造 this.getters 对象
Object.defineProperty(this.getters, key, {
get: () => {
return options.getters[key](this.state)
}
})
})
}
}
但如果这样写的 话, 就不能像原先那样调用了,需要多调一层 state才能拿到数据, (使用类的属性访问器setter, getter)解决这个问题,参考 es6文档
改写代码如下:
class Store {
constructor(options = {}) {
this.myState = new Vue({
data() {
return {
state: options.state
}
}
})
// 定义实例上的 getters
this.getters = {}
// 遍历所有的对象中的方法名
Object.keys(options.getters).forEach(key => {
// 重新构造 this.getters 对象
Object.defineProperty(this.getters, key, {
get: () => {
return options.getters[key](this.state)
}
})
})
}
get state() {
return this.myState.state
}
}
到这里,已经基本实现了, 数据响应式变化, state, getters 了
整体代码:
let Vue
class Store {
constructor(options = {}) {
// 核心代码: 保证数据都是响应式的
this.myState = new Vue({
data() {
return {
state: options.state
}
}
})
// 定义实例上的 getters
this.getters = {}
// 遍历所有的对象中的方法名
Object.keys(options.getters).forEach(key => {
// 重新构造 this.getters 对象
Object.defineProperty(this.getters, key, {
get: () => {
return options.getters[key](this.state)
}
})
})
}
get state() {
return this.myState.state
}
}
const install = _Vue => {
console.log("install")
Vue = _Vue // 用一个变量接收 _Vue 构造器
Vue.mixin({
beforeCreate() {
//判断 根 实例 有木有传入store 数据源,
//如果传入了, 就把它放到实例的 $store上
if (this.$options && this.$options.store) {
this.$store = this.$options.store
} else {
// 2. 子组件去取父级组件的$store属性
this.$store = this.$parent && this.$parent.$store
}
}
})
}
export default {
install,
Store
}
let mutations = {} // 定义一个对象收集所有传入的 mutations
Object.keys(options.mutations).forEach(key => {
mutations[key] = () => {
}
})
// 提供commit 方法
this.commit = (key, payload) => {
mutations[key](payload)
}
// 定义 muations
let mutations = {}
Object.keys(options.mutations).forEach(key => {
mutations[key] = payload => {
options.mutations[key](this.state, payload)
}
})
let Vue
class Store {
constructor(options = {}) {
// 核心代码: 保证数据都是响应式的
this.myState = new Vue({
data() {
return {
state: options.state
}
}
})
// 定义实例上的 getters
this.getters = {}
// 遍历所有的对象中的方法名
Object.keys(options.getters).forEach(key => {
// 重新构造 this.getters 对象
Object.defineProperty(this.getters, key, {
get: () => {
return options.getters[key](this.state)
}
})
})
// 定义 muations
let mutations = {}
Object.keys(options.mutations).forEach(key => {
mutations[key] = payload => {
options.mutations[key](this.state, payload)
}
})
// 提供commit 方法
this.commit = (key, payload) => {
mutations[key](payload)
}
}
get state() {
return this.myState.state
}
}
const install = _Vue => {
console.log("install")
Vue = _Vue // 用一个变量接收 _Vue 构造器
Vue.mixin({
beforeCreate() {
//判断 根 实例 有木有传入store 数据源,
//如果传入了, 就把它放到实例的 $store上
if (this.$options && this.$options.store) {
this.$store = this.$options.store
} else {
// 2. 子组件去取父级组件的$store属性
this.$store = this.$parent && this.$parent.$store
}
}
})
}
export default {
install,
Store
}
// 收集 actions
let actions = {}
Object.keys(options.actions).forEach(key => {
actions[key] = payload => {
options.actions[key](this, payload)
}
})
this.dispatch = (key, payload) => {
actions[key](payload)
}
let Vue
class Store {
constructor(options = {}) {
// 核心代码: 保证数据都是响应式的
this.myState = new Vue({
data() {
return {
state: options.state
}
}
})
// 定义实例上的 getters
this.getters = {}
// 遍历所有的对象中的方法名
Object.keys(options.getters).forEach(key => {
// 重新构造 this.getters 对象
Object.defineProperty(this.getters, key, {
get: () => {
return options.getters[key](this.state)
}
})
})
// 定义 muations
let mutations = {}
Object.keys(options.mutations).forEach(key => {
mutations[key] = payload => {
options.mutations[key](this.state, payload)
}
})
// 提供commit 方法
this.commit = (key, payload) => {
mutations[key](payload)
}
// 收集 actions
let actions = {}
Object.keys(options.actions).forEach(key => {
actions[key] = payload => {
options.actions[key](this, payload)
}
})
this.dispatch = (key, payload) => {
actions[key](payload)
}
}
get state() {
return this.myState.state
}
}
const install = _Vue => {
console.log("install")
Vue = _Vue // 用一个变量接收 _Vue 构造器
Vue.mixin({
beforeCreate() {
//判断 根 实例 有木有传入store 数据源,
//如果传入了, 就把它放到实例的 $store上
if (this.$options && this.$options.store) {
this.$store = this.$options.store
} else {
// 2. 子组件去取父级组件的$store属性
this.$store = this.$parent && this.$parent.$store
}
}
})
}
export default {
install,
Store
}
参考:https://blog.csdn.net/qq_36407748/article/details/102778062