希腊网站后缀网站整站优化
一、综合案例 - 创建项目
本案例主要针对Vuex共享数据的练习以及父子组件数据的共享。
-
脚手架新建项目 (注意:勾选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/index.js
import Vuex from 'vuex'
import Vue from 'vue'import cart from './modules/cart'Vue.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 目录
{ "cart": [{"id": 100001,"name": "低帮城市休闲户外鞋天然牛皮COOLMAX纤维","price": 128,"count": 1,"thumb": "https://yanxuan-item.nosdn.127.net/3a56a913e687dc2279473e325ea770a9.jpg"},{"id": 100002,"name": "网易味央黑猪猪肘330g*1袋","price": 39,"count": 14,"thumb": "https://yanxuan-item.nosdn.127.net/d0a56474a8443cf6abd5afc539aa2476.jpg"},{"id": 100003,"name": "KENROLL男女简洁多彩一片式室外拖","price": 128,"count": 2,"thumb": "https://yanxuan-item.nosdn.127.net/eb1556fcc59e2fd98d9b0bc201dd4409.jpg"},{"id": 100004,"name": "云音乐定制IN系列intar民谣木吉他","price": 589,"count": 1,"thumb": "https://yanxuan-item.nosdn.127.net/4d825431a3587edb63cb165166f8fc76.jpg"} ] }
- 进入 db 目录,执行命令,启动后端接口服务 (使用-
- -watch 参数 可以实时监听 json 文件的修改)
json-server --watch index.json
当服务启动后,可以访问http://localhost:3000/cart
获取数据
四、综合案例-请求动态渲染数据
1.目标
请求获取数据存入 vuex, 映射渲染
- 安装 axios
yarn add axios
- 准备actions 和 mutations
import axios from 'axios'export 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 'vuex'export default {name: 'App',components: {CartHeader,CartFooter,CartItem},created () {this.$store.dispatch('cart/getList')},computed: {...mapState('cart', ['list'])}
}
- 动态渲染
<!-- 商品 Item 项组件 -->
<cart-item v-for="item in list" :key="item.id" :item="item"></cart-item>
cart-item.vue
<template><div class="goods-container"><!-- 左侧图片区域 --><div class="left"><img :src="item.thumb" class="avatar" alt=""></div><!-- 右侧商品区域 --><div class="right"><!-- 标题 --><div class="title">{{item.name}}</div><div class="info"><!-- 单价 --><span class="price">¥{{item.price}}</span><div class="btns"><!-- 按钮区域 --><button class="btn btn-light">-</button><span class="count">{{item.count}}</span><button class="btn btn-light">+</button></div></div></div></div>
</template><script>
export default {name: 'CartItem',props: {item: Object},methods: {}
}
</script>
五、综合案例-修改数量
- 注册点击事件
<!-- 按钮区域 -->
<button class="btn btn-light" @click="onBtnClick(-1)">-</button>
<span class="count">{{item.count}}</span>
<button class="btn btn-light" @click="onBtnClick(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);},
},
- 动态渲染
<template><div class="footer-container"><!-- 中间的合计 --><div><span>共 {{total}} 件商品,合计:</span><span class="price">¥{{totalPrice}}</span></div><!-- 右侧结算按钮 --><button class="btn btn-success btn-settle">结算</button></div>
</template><script>
import { mapGetters } from 'vuex'
export default {name: 'CartFooter',computed: {...mapGetters('cart', ['total', 'totalPrice'])}
}
</script>