宜昌做网站哪家最便宜,做网站需要审核资质吗,微信公众号线上商城怎么做,企石镇仿做网站一、Vuex 概述
目标#xff1a;明确Vuex是什么#xff0c;应用场景以及优势
1.是什么
Vuex 是一个 Vue 的 状态管理工具#xff0c;状态就是数据。
大白话#xff1a;Vuex 是一个插件#xff0c;可以帮我们管理 Vue 通用的数据 (多组件共享的数据)。例如#xff1a;购…一、Vuex 概述
目标明确Vuex是什么应用场景以及优势
1.是什么
Vuex 是一个 Vue 的 状态管理工具状态就是数据。
大白话Vuex 是一个插件可以帮我们管理 Vue 通用的数据 (多组件共享的数据)。例如购物车数据 个人信息数
2.使用场景 某个状态 在 很多个组件 来使用 (个人信息) 多个组件 共同维护 一份数据 (购物车) 3.优势
共同维护一份数据数据集中化管理响应式变化操作简洁 (vuex提供了一些辅助函数) 4.注意
官方原文
不是所有的场景都适用于vuex只有在必要的时候才使用vuex使用了vuex之后会附加更多的框架中的概念进来增加了项目的复杂度 数据的操作更便捷数据的流动更清晰
Vuex就像《近视眼镜》, 你自然会知道什么时候需要用它~
二、需求: 多组件共享数据
目标基于脚手架创建项目构建 vuex 多组件数据共享环境 效果是三个组件共享一份数据:
任意一个组件都可以修改数据三个组件的数据是同步的
1.创建项目
vue create vuex-demo2.创建三个组件, 目录如下
|-components
|--Son1.vue
|--Son2.vue
|-App.vue3.源代码如下
App.vue在入口组件中引入 Son1 和 Son2 这两个子组件
templatediv idapph1根组件/h1input typetextSon1/Son1hrSon2/Son2/div
/templatescript
import Son1 from ./components/Son1.vue
import Son2 from ./components/Son2.vueexport default {name: app,data: function () {return {}},components: {Son1,Son2}
}
/scriptstyle
#app {width: 600px;margin: 20px auto;border: 3px solid #ccc;border-radius: 3px;padding: 10px;
}
/style
main.js
import Vue from vue
import App from ./App.vueVue.config.productionTip falsenew Vue({render: h h(App)
}).$mount(#app)Son1.vue
templatediv classboxh2Son1 子组件/h2从vuex中获取的值: label/labelbrbutton值 1/button/div
/templatescript
export default {name: Son1Com
}
/scriptstyle langcss scoped
.box{border: 3px solid #ccc;width: 400px;padding: 10px;margin: 20px;
}
h2 {margin-top: 10px;
}
/style
Son2.vue
templatediv classboxh2Son2 子组件/h2从vuex中获取的值:label/labelbr /button值 - 1/button/div
/templatescript
export default {name: Son2Com
}
/scriptstyle langcss scoped
.box {border: 3px solid #ccc;width: 400px;padding: 10px;margin: 20px;
}
h2 {margin-top: 10px;
}
/style三、vuex 的使用 - 创建仓库 1.安装 vuex
安装vuex与vue-router类似vuex是一个独立存在的插件如果脚手架初始化没有选 vuex就需要额外安装。
yarn add vuex3 或者 npm i vuex32.新建 store/index.js 专门存放 vuex
为了维护项目目录的整洁在src目录下新建一个store目录其下放置一个index.js文件。 (和 router/index.js 类似)
3.创建仓库 store/index.js
// 导入 vue
import Vue from vue
// 导入 vuex
import Vuex from vuex
// vuex也是vue的插件, 需要use一下, 进行插件的安装初始化
Vue.use(Vuex)// 创建仓库 store
const store new Vuex.Store()// 导出仓库
export default store4 在 main.js 中导入挂载到 Vue 实例上
import Vue from vue
import App from ./App.vue
import store from ./storeVue.config.productionTip falsenew Vue({render: h h(App),store
}).$mount(#app)此刻起, 就成功创建了一个 空仓库!!
5.测试打印Vuex
App.vue
created(){console.log(this.$store)
}四、核心概念 - state 状态
1.目标
明确如何给仓库 提供 数据如何 使用 仓库的数据
2.提供数据
State提供唯一的公共数据源所有共享的数据都要统一放到Store中的State中存储。
打开项目中的store.js文件在state对象中可以添加我们要共享的数据。
// 创建仓库 store
const store new Vuex.Store({// state 状态, 即数据, 类似于vue组件中的data,// 区别// 1.data 是组件自己的数据, // 2.state 中的数据整个vue项目的组件都能访问到state: {count: 101}
})3.访问Vuex中的数据
问题: 如何在组件中获取count?
通过$store直接访问 — {{ $store.state.count }}通过辅助函数mapState 映射计算属性 — {{ count }}
4.通过$store访问的语法
获取 store1.Vue模板中获取 this.$store2.js文件中获取 import 导入 store模板中 {{ $store.state.xxx }}
组件逻辑中 this.$store.state.xxx
JS模块中 store.state.xxx5.代码实现
5.1模板中使用
组件中可以使用 $store 获取到vuex中的store对象实例可通过state属性属性获取count 如下
h1state的数据 - {{ $store.state.count }}/h15.2组件逻辑中使用
将state属性定义在计算属性中 https://vuex.vuejs.org/zh/guide/state.html
h1state的数据 - {{ count }}/h1// 把state中数据定义在组件内的计算属性中computed: {count () {return this.$store.state.count}}5.3 js文件中使用
//main.jsimport store from /storeconsole.log(store.state.count)每次都像这样一个个的提供计算属性, 太麻烦了,我们有没有简单的语法帮我们获取state中的值呢
五、通过辅助函数 - mapState获取 state中的数据 mapState是辅助函数帮助我们把store中的数据映射到 组件的计算属性中, 它属于一种方便的用法 用法 1.第一步导入mapState (mapState是vuex中的一个函数)
import { mapState } from vuex2.第二步采用数组形式引入state属性
mapState([count]) 上面代码的最终得到的是 类似于 count () {return this.$store.state.count
}3.第三步利用展开运算符将导出的状态映射给计算属性 computed: {...mapState([count])}div state的数据{{ count }}/div六、开启严格模式及Vuex的单项数据流
1.目标
明确 vuex 同样遵循单向数据流组件中不能直接修改仓库的数据
2.直接在组件中修改Vuex中state的值 Son1.vue
button clickhandleAdd值 1/buttonmethods:{handleAdd (n) {// 错误代码(vue默认不会监测监测需要成本)this.$store.state.count// console.log(this.$store.state.count) },
}3.开启严格模式
通过 strict: true 可以开启严格模式,开启严格模式后直接修改state中的值会报错 state数据的修改只能通过mutations并且mutations必须是同步的 七、核心概念-mutations
1.定义mutations
const store new Vuex.Store({state: {count: 0},// 定义mutationsmutations: {}
})2.格式说明
mutations是一个对象对象中存放修改state的方法
mutations: {// 方法里参数 第一个参数是当前store的state属性// payload 载荷 运输参数 调用mutations的时候 可以传递参数 传递载荷addCount (state) {state.count 1}},3.组件中提交 mutations
this.$store.commit(addCount)4.练习
1.在mutations中定义个点击按钮进行 5 的方法
2.在mutations中定义个点击按钮进行 改变title 的方法
3.在组件中调用mutations修改state中的值
5.总结
通过mutations修改state的步骤
1.定义 mutations 对象对象中存放修改 state 的方法
2.组件中提交调用 mutations(通过$store.commit(‘mutations的方法名’))
八、带参数的 mutations
1.目标
掌握 mutations 传参语法
2.语法
看下面这个案例每次点击不同的按钮加的值都不同每次都要定义不同的mutations处理吗 提交 mutation 是可以传递参数的 this.$store.commit(xxx, 参数)
2.1 提供mutation函数带参数
mutations: {...addCount (state, count) {state.count count}
},2.2 提交mutation
handle ( ) {this.$store.commit(addCount, 10)
}小tips: 提交的参数只能是一个, 如果有多个参数要传, 可以传递一个对象
this.$store.commit(addCount, {count: 10
})九、练习-mutations的减法功能 1.步骤 2.代码实现
Son2.vue button clicksubCount(1)值 - 1/buttonbutton clicksubCount(5)值 - 5/buttonbutton clicksubCount(10)值 - 10/buttonexport default {methods:{subCount (n) { this.$store.commit(subCount, n)},}}store/index.js
mutations:{subCount (state, n) {state.count - n},
}十、练习-Vuex中的值和组件中的input双向绑定
1.目标
实时输入实时更新巩固 mutations 传参语法 2.实现步骤 3.代码实现
App.vue
input :valuecount inputhandleInput typetextexport default {methods: {handleInput (e) {// 1. 实时获取输入框的值const num e.target.value// 2. 提交mutation调用mutation函数this.$store.commit(changeCount, num)}}
}store/index.js
mutations: { changeCount (state, newCount) {state.count newCount}
},十一、辅助函数- mapMutations mapMutations和mapState很像它把位于mutations中的方法提取了出来我们可以将它导入 import { mapMutations } from vuex
methods: {...mapMutations([addCount])
}上面代码的含义是将mutations的方法导入了methods中等价于 methods: {// commit(方法名, 载荷参数)addCount () {this.$store.commit(addCount)}}此时就可以直接通过this.addCount调用了
button clickaddCount值1/button但是请注意 Vuex中mutations中要求不能写异步代码如果有异步的ajax请求应该放置在actions中
十二、核心概念 - actions state是存放数据的mutations是同步更新数据 (便于监测数据的变化, 更新视图等, 方便于调试工具查看变化) actions则负责进行异步操作 说明mutations必须是同步的
需求: 一秒钟之后, 要给一个数 去修改state 1.定义actions
mutations: {changeCount (state, newCount) {state.count newCount}
}actions: {setAsyncCount (context, num) {// 一秒后, 给一个数, 去修改 numsetTimeout(() {context.commit(changeCount, num)}, 1000)}
},2.组件中通过dispatch调用
setAsyncCount () {this.$store.dispatch(setAsyncCount, 666)
}十三、辅助函数 -mapActions
1.目标掌握辅助函数 mapActions映射方法 mapActions 是把位于 actions中的方法提取了出来映射到组件methods中 Son2.vue
import { mapActions } from vuex
methods: {...mapActions([setAsyncCount]),changeCountAction(n) {this.setAsyncCount(n)}
}
直接通过 this.方法 就可以调用
button clickchangeCountAction(200)异步/button十四、核心概念 - getters 除了state之外有时我们还需要从state中筛选出符合条件的一些数据这些数据是依赖state的此时会用到getters 例如state中定义了list为1-10的数组
state: {list: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
}组件中需要显示所有大于5的数据正常的方式是需要list在组件中进行再一步的处理但是getters可以帮助我们实现它
1.定义getters getters: {// getters函数的第一个参数是 state// 必须要有返回值filterList: state state.list.filter(item item 5)}2.使用getters
2.1原始方式-$store
div{{ $store.getters.filterList }}/div2.2辅助函数 - mapGetters
computed: {...mapGetters([filterList])
}div{{ filterList }}/div十五、使用小结 十六、核心概念 - module
1.目标
掌握核心概念 module 模块的创建
2.问题
由于使用单一状态树应用的所有状态会集中到一个比较大的对象。当应用变得非常复杂时store 对象就有可能变得相当臃肿。
这句话的意思是如果把所有的状态都放在state中当项目变得越来越大的时候Vuex会变得越来越难以维护
由此又有了Vuex的模块化 3.模块定义 - 准备 state
定义两个模块 user 和 setting
user中管理用户的信息状态 userInfo modules/user.js
const state {userInfo: {name: zs,age: 18}
}const mutations {}const actions {}const getters {}export default {state,mutations,actions,getters
}
setting中管理项目应用的 主题色 theme描述 desc modules/setting.js
const state {theme: darkdesc: 描述真呀真不错
}const mutations {}const actions {}const getters {}export default {state,mutations,actions,getters
}在store/index.js文件中的modules配置项中注册这两个模块
import user from ./modules/user
import setting from ./modules/settingconst store new Vuex.Store({modules:{user,setting}
})使用模块中的数据, 可以直接通过模块名访问 $store.state.模块名.xxx $store.state.setting.desc
也可以通过 mapState 映射
十七、获取模块内的state数据
1.目标
掌握模块中 state 的访问语法
尽管已经分模块了但其实子模块的状态还是会挂到根级别的 state 中属性名就是模块名 2.使用模块中的数据
直接通过模块名访问 $store.state.模块名.xxx通过 mapState 映射默认根级别的映射 mapState([ ‘xxx’ ])子模块的映射 mapState(‘模块名’, [‘xxx’]) - 需要开启命名空间 namespaced:true
modules/user.js
const state {userInfo: {name: zs,age: 18},myMsg: 我的数据
}const mutations {updateMsg (state, msg) {state.myMsg msg}
}const actions {}const getters {}export default {namespaced: true,state,mutations,actions,getters
}3.代码示例
$store直接访问
$store.state.user.userInfo.namemapState辅助函数访问
...mapState(user, [userInfo]),
...mapState(setting, [theme, desc]),十八、获取模块内的getters数据
1.目标
掌握模块中 getters 的访问语
2.语法
使用模块中 getters 中的数据
直接通过模块名访问 $store.getters[模块名/xxx ]通过 mapGetters 映射 默认根级别的映射 mapGetters([ xxx ]) 子模块的映射 mapGetters(模块名, [xxx]) - 需要开启命名空间
3.代码演示
modules/user.js
const getters {// 分模块后state指代子模块的stateUpperCaseName (state) {return state.userInfo.name.toUpperCase()}
}Son1.vue 直接访问getters
!-- 测试访问模块中的getters - 原生 --
div{{ $store.getters[user/UpperCaseName] }}/divSon2.vue 通过命名空间访问
computed:{...mapGetters(user, [UpperCaseName])
}十九、获取模块内的mutations方法
1.目标
掌握模块中 mutation 的调用语法
2.注意
默认模块中的 mutation 和 actions 会被挂载到全局需要开启命名空间才会挂载到子模块。
3.调用方式
直接通过 store 调用 $store.commit(模块名/xxx , 额外参数)通过 mapMutations 映射 默认根级别的映射 mapMutations([ ‘xxx’ ])子模块的映射 mapMutations(‘模块名’, [‘xxx’]) - 需要开启命名空间
4.代码实现
modules/user.js
const mutations {setUser (state, newUserInfo) {state.userInfo newUserInfo}
}modules/setting.js
const mutations {setTheme (state, newTheme) {state.theme newTheme}
}Son1.vue
button clickupdateUser更新个人信息/button
button clickupdateTheme更新主题色/buttonexport default {methods: {updateUser () {// $store.commit(模块名/mutation名, 额外传参)this.$store.commit(user/setUser, {name: xiaowang,age: 25})}, updateTheme () {this.$store.commit(setting/setTheme, pink)}}
}Son2.vue
button clicksetUser({ name: xiaoli, age: 80 })更新个人信息/button
button clicksetTheme(skyblue)更新主题/buttonmethods:{
// 分模块的映射
...mapMutations(setting, [setTheme]),
...mapMutations(user, [setUser]),
}二十、获取模块内的actions方法
1.目标
掌握模块中 action 的调用语法 (同理 - 直接类比 mutation 即可)
2.注意
默认模块中的 mutation 和 actions 会被挂载到全局需要开启命名空间才会挂载到子模块。
3.调用语法
直接通过 store 调用 $store.dispatch(模块名/xxx , 额外参数)通过 mapActions 映射 默认根级别的映射 mapActions([ ‘xxx’ ])子模块的映射 mapActions(‘模块名’, [‘xxx’]) - 需要开启命名空间
4.代码实现
需求 modules/user.js
const actions {setUserSecond (context, newUserInfo) {// 将异步在action中进行封装setTimeout(() {// 调用mutation context上下文默认提交的就是自己模块的action和mutationcontext.commit(setUser, newUserInfo)}, 1000)}
}Son1.vue 直接通过store调用
button clickupdateUser2一秒后更新信息/buttonmethods:{updateUser2 () {// 调用action dispatchthis.$store.dispatch(user/setUserSecond, {name: xiaohong,age: 28})},
}Son2.vue mapActions映射
button clicksetUserSecond({ name: xiaoli, age: 80 })一秒后更新信息/buttonmethods:{...mapActions(user, [setUserSecond])
}二十一、Vuex模块化的使用小结
1.直接使用
state -- $store.state.模块名.数据项名getters -- $store.getters[‘模块名/属性名’]mutations -- $store.commit(‘模块名/方法名’, 其他参数)actions -- $store.dispatch(‘模块名/方法名’, 其他参数)
2.借助辅助方法使用
1.import { mapXxxx, mapXxx } from ‘vuex’
computed、methods: {
// …mapState、…mapGetters放computed中
// …mapMutations、…mapActions放methods中
…mapXxxx(‘模块名’, [‘数据项|方法’]),
…mapXxxx(‘模块名’, { 新的名字: 原来的名字 }),
}
2.组件中直接使用 属性 {{ age }} 或 方法 clickupdateAge(2)
二十二、综合案例 - 创建项目 脚手架新建项目 (注意勾选vuex) 版本说明 vue2 vue-router3 vuex3 vue3 vue-router4 vuex4/pinia
vue create vue-cart-demo将原本src内容清空替换成教学资料的《vuex-cart-准备代码》 需求
发请求动态渲染购物车数据存vuex 存cart模块 将来还会有user模块article模块…数字框可以修改数据动态计算总价和总数量
二十三、综合案例-构建vuex-cart模块
新建 store/modules/cart.js
export default {namespaced: true,state () {return {list: []}},
}挂载到 vuex 仓库上 store/cart.js
import Vuex from vuex
import Vue from vueimport cart from ./modules/cartVue.use(Vuex)const store new Vuex.Store({modules: {cart}
})export default store二十四、综合案例-准备后端接口服务环境(了解)
安装全局工具 json-server 全局工具仅需要安装一次
yarn global add json-server 或 npm i json-server -g代码根目录新建一个 db 目录将资料 index.json 移入 db 目录进入 db 目录执行命令启动后端接口服务 (使用–watch 参数 可以实时监听 json 文件的修改)
json-server --watch index.json二十五、综合案例-请求动态渲染数据
1.目标
请求获取数据存入 vuex, 映射渲染 安装 axios
yarn add axios准备actions 和 mutations
import axios from axiosexport default {namespaced: true,state () {return {list: []}},mutations: {updateList (state, payload) {state.list payload}},actions: {async getList (ctx) {const res await axios.get(http://localhost:3000/cart)ctx.commit(updateList, res.data)}}
}App.vue页面中调用 action, 获取数据
import { mapState } from vuexexport default {name: App,components: {CartHeader,CartFooter,CartItem},created () {this.$store.dispatch(cart/getList)},computed: {...mapState(cart, [list])}
}动态渲染
!-- 商品 Item 项组件 --
cart-item v-foritem in list :keyitem.id :itemitem/cart-itemcart-item.vue
templatediv classgoods-container!-- 左侧图片区域 --div classleftimg :srcitem.thumb classavatar alt/div!-- 右侧商品区域 --div classright!-- 标题 --div classtitle{{item.name}}/divdiv classinfo!-- 单价 --span classprice{{item.price}}/spandiv classbtns!-- 按钮区域 --button classbtn btn-light-/buttonspan classcount{{item.count}}/spanbutton classbtn btn-light/button/div/div/div/div
/templatescript
export default {name: CartItem,props: {item: Object},methods: {}
}
/script二十六、综合案例-修改数量 注册点击事件
!-- 按钮区域 --
button classbtn btn-light clickonBtnClick(-1)-/button
span classcount{{item.count}}/span
button classbtn btn-light clickonBtnClick(1)/button页面中dispatch action
onBtnClick (step) {const newCount this.item.count stepif (newCount 1) return// 发送修改数量请求this.$store.dispatch(cart/updateCount, {id: this.item.id,count: newCount})
}提供action函数
async updateCount (ctx, payload) {await axios.patch(http://localhost:3000/cart/ payload.id, {count: payload.count})ctx.commit(updateCount, payload)
}提供mutation处理函数
mutations: {...,updateCount (state, payload) {const goods state.list.find((item) item.id payload.id)goods.count payload.count}
},二十七、综合案例-底部总价展示
提供getters
getters: {total(state) {return state.list.reduce((p, c) p c.count, 0);},totalPrice (state) {return state.list.reduce((p, c) p c.count * c.price, 0);},
},动态渲染
templatediv classfooter-container!-- 中间的合计 --divspan共 {{total}} 件商品合计/spanspan classprice{{totalPrice}}/span/div!-- 右侧结算按钮 --button classbtn btn-success btn-settle结算/button/div
/templatescript
import { mapGetters } from vuex
export default {name: CartFooter,computed: {...mapGetters(cart, [total, totalPrice])}
}
/script