内容简介:在vue中涉及到比较复杂的数据流转、交互,我们一般都会考虑用vux来进行数据的状态管理。经常使用,时常想它是怎么实现的,尝试简易实现一下。遗憾的是这不能正常工作,这是为什么?因为Vue使用数据方法来触发其“响应式反应”。如果不将数据传递给data,Vue将无法跟踪值更改并更新我们的组件以作为响应,更新视图。修改一下。注意
在vue中涉及到比较复杂的数据流转、交互,我们一般都会考虑用vux来进行数据的状态管理。经常使用,时常想它是怎么实现的,尝试简易实现一下。
- 以选举日为例,一般的组件写法
<template> <div> <h1>Election day!</h1> <button @click="voteForRed">Vote for :red_circle:</button> <button @click="voteForBlue">Vote for :large_blue_circle:</button> <h2>Results</h2> <results :red="red" :blue="blue" /> <total-votes :total="red + blue" /> </div> </template> <script> const TotalVotes = { props: ['total'], render (h) { return h('div', `Total votes: ${this.total}`) } } const Results = { props: ['red', 'blue'], render (h) { return h('div', `Red: ${this.red} - Blue: ${this.blue}`) } } export default { components: { TotalVotes, Results, }, data: () => ({ red: 0, blue: 0 }), methods: { voteForRed () { this.red++ }, voteForBlue () { this.blue++ }, } } </script> 复制代码
- 隔离状态 让我们创建一个state对象,并从那里管理我们的整转态。
const state = { red: 0, blue: 0, } const TotalVotes = { render: h => h('div', `Total votes: ${state.red + state.blue}`) } const Results = { render: h => h('div', `Red: ${state.red} - Blue: ${state.blue}`), } // ...and, inside our main component,... methods: { voteForRed () { state.red++ }, voteForBlue () { state.blue++ }, }, 复制代码
遗憾的是这不能正常工作,这是为什么?因为Vue使用数据方法来触发其“响应式反应”。如果不将数据传递给data,Vue将无法跟踪值更改并更新我们的组件以作为响应,更新视图。修改一下。
<template> <div> <h1>Election day!</h1> <button @click="voteForRed">Vote for :red_circle:</button> <button @click="voteForBlue">Vote for :large_blue_circle:</button> <h2>Results</h2> <results/> <total-votes/> </div> </template> <script> const state = { red: 0, blue: 0, } const TotalVotes = { data () { return state }, render (h) { return h('div', `Total votes: ${this.red + this.blue}`) }, } const Results = { data () { return state }, render (h) { return h('div', `Red: ${this.red} - Blue: ${this.blue}`) }, } export default { components: { TotalVotes, Results }, data () { return state }, methods: { voteForRed () { this.red++ }, voteForBlue () { this.blue++ }, }, } </script> 复制代码
注意
-
组件TotalVotes、Results的props已经去除
-
每一个组件在state中注册了state,Vue能够追踪状态变化,因此当我们投票给所有组件时,所有组件都会以适当的值进行重新渲染
-
渲染函数中删除了箭头函数
-
上面的实现方式存在缺陷,每个组件都要注册state,耦合性较高,继续改进
-
创建共享Vue实例以保持响应式(数据变化触发视图更新)
import Vue from 'vue' const state = new Vue({ data () { return { red: 0, blue: 0 } }, methods: { voteForRed () { this.red++ }, voteForBlue () { this.blue++ }, }, }) const TotalVotes = { render: h => h('div', `Total votes: ${state.red + state.blue}`), } const Results = { render: h => h('div', `Red: ${state.red} - Blue: ${state.blue}`), } export default { components: { TotalVotes, Results }, methods: { voteForRed () { state.voteForRed() }, voteForBlue () { state.voteForBlue() }, }, } 复制代码
至此实现了简单的状态管理,但我们的解决方案目前无法在项目之间共享。我需要创建一个Vue实例,填充其数据方法,然后注册一些方法来修改状态,继续封装。
- 封装
<!--模板--> <template> <div> <h1>Election day!</h1> <button @click="voteForRed">Vote for :red_circle:</button> <button @click="voteForBlue">Vote for :large_blue_circle:</button> <h2>Results</h2> <results :red="red" :blue="blue" /> <total-votes :total="red + blue" /> </div> </template> <!--js--> <script> import Vue from 'vue' const createStore = ({state, mutations}) => { return new Vue({ data () { return {state} }, methods: { commit (mutationName) { mutations[mutationName](this.state) } } }) } const store = createStore({ state: { red: 0, blue: 0 }, mutations: { voteForRed (state) { state.red++ }, voteForBlue (state) { state.blue++ } } }) const TotalVotes = { render: h => h('div', `Total votes: ${store.state.red + store.state.blue}`) } const Results = { render: h => h('div', `Red: ${store.state.red} - Blue: ${store.state.blue}`) } export default { components: { TotalVotes, Results }, methods: { voteForRed () { store.commit('voteForRed') }, voteForBlue () { store.commit('voteForBlue') } } } </script> 复制代码
以上所述就是小编给大家介绍的《vue状态管理演进》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
SHA 加密
SHA 加密工具
UNIX 时间戳转换
UNIX 时间戳转换