Vue3 + Vuex4 构建点餐页面
2020/5/5 11:26:13
本文主要是介绍Vue3 + Vuex4 构建点餐页面,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
前言
前进!前进!不择手段地前进!!
距离Vue3.0 beta 发布已经过了半个多月了。本来这个东西上个月就应该写了,由于公司上个月赶项目一直没时间。趁着劳动节把这个东西写了一下,也顺便把一些坑过了一下。
介绍
页面比较简单,算是把 Composition API
过了一下了
- 基于
Vue3.0 beta
这种页面也比较老套
了 - 涉及了
Vue3.0 beta
andVuex4 beta
andaxios
安装vue3环境
题外话: 听说
vite
不错,这几天得了解下🤪
- 安装(升级)最近的
vue-cli
vue create projectName
ps: 如果自己不会手动装vuex4
或者vue-router4
这些库最好是直接安装步骤全部安装(减少一些踩坑的时间成本)vue add vue-next
这个命令会把项目中的一些依赖自动升级成支持vue3的版本npm run serve
Composition-API
这里建议直接看文档 vue-composition-api-rfc.netlify.app/#summary
🤐直接贴代码了
毕竟思路都差不多,可以的话建议直接看 github.com/notbucai/vu…
useScroll
import { ref } from 'vue'; export const useScrollTop = () => { const top = ref(0); window.addEventListener('scroll', () => { const scrollTop = document.documentElement.scrollTop; top.value = scrollTop; }); return top; } 复制代码
store
import { createStore } from "vuex"; export default createStore({ state: { shopcart: {}, foodList: [], }, getters: { // TODO: 这里的金额计算 是"有问题"的 // 计算金额与数量 settlement(state) { let allPrice = 0; let allCount = 0; const shopcart = state.shopcart; const foodList = state.foodList; // 得到所有食物列表 const foods = foodList.reduce((previousValue, currentValue) => { return previousValue.concat(currentValue.foods); }, []); // 通过购物车计算金额数量 Object.keys(shopcart).forEach(key => { const count = shopcart[key]; if (!count) return; const food = foods.find(item => item.item_id == key); const price = food.specfoods[0].price; // 这里只是一种简单的处理浮点金额的方案(不保险),实际上后端直接返回以分为单位的金额会更好,【在后端计算金额一定情况下可能更靠谱】 allPrice += (price * 10000 * count); allCount += count; }); return { price: allPrice / 10000, count: allCount, } } }, mutations: { ADD_ITEM(state, id) { state.shopcart[id] = state.shopcart[id] || 0; state.shopcart[id]++; }, SUB_ITEM(state, id) { state.shopcart[id] = state.shopcart[id] || 0; state.shopcart[id]--; }, SET_FOOD_LIST(state, payload) { state.foodList = payload; } }, actions: { setFoodList({ commit }, payload) { commit('SET_FOOD_LIST', payload) }, addItem({ commit }, id) { commit('ADD_ITEM', id) }, subItem({ commit }, id) { commit('SUB_ITEM', id) }, } }); 复制代码
页面
<template> <div class="Catering"> <header class="header"> <div class="shop"> <div class="shop-pic"> <img src="https://upload.jianshu.io/users/upload_avatars/7759683/995f635d-357b-4539-b008-55aa6b0ac140.jpg?imageMogr2/auto-orient/strip|imageView2/1/w/96/h/96/format/webp" alt /> </div> <div class="shop-name">一袋米</div> </div> <div class="navbar"> <div class="nav-item">点餐</div> <div class="nav-item">评价</div> <div class="nav-item">商家</div> </div> <div class="outher-box"></div> </header> <main class="main"> <div class="left"> <div class="left-item" v-for="(item, index) in list" :class="{active:elIndex == index}" :key="index" @click="srcollTo(index)" >{{item.name}}</div> </div> <div class="right"> <template v-for="(_item, index) in list"> <!-- 这里的ref就又点难受了 --> <div :key="index" :ref="el=>itemEls[index] = el"> <food-item :item="_item" /> </div> </template> </div> <settlement-bottom /> </main> </div> </template> <script> import { watch, ref, onBeforeUpdate, onMounted, computed } from 'vue'; import { useStore } from 'vuex'; import { useScrollTop } from '../hooks'; import { getList } from '../ajax/index'; import FoodItem from './components/FoodItem'; import SettlementBottom from './components/SettlementBottom'; export default { components: { FoodItem, SettlementBottom }, setup() { // store const store = useStore(); const list = computed(() => store.state.foodList); onMounted(async () => { // NOTE: 获取数据 let resList = await getList(); // 存入store store.dispatch('setFoodList', resList); }); // 组节点列表 const itemEls = ref([]); // 当前选中节点 const elIndex = ref(0); // 监听数据 const scrollTop = useScrollTop([]); onBeforeUpdate(() => { // 更新时清空 itemEls.value = []; }); // 监听滚动条变化 watch(scrollTop, () => { let index = 0; // 判断距离头部最近的元素 实际上这里是可以缓存高度的 itemEls.value.forEach((el, i) => { // console.log('el=>',el,'val=>', scrollTop.value); if (el.offsetTop > scrollTop.value) return; index = i; }); // 绑定节点 elIndex.value = index; }); const srcollTo = index => { elIndex.value = index; const el = itemEls.value[index]; const offsetTop = el.offsetTop; window.scrollTo(0, offsetTop); }; return { list, itemEls, elIndex, srcollTo }; } }; </script> <style lang="scss"> ...... </style> 复制代码
FoodItem.vue
<template> <div class="FoodItem"> <div class="food-title">{{item.name}}</div> <div class="food-item" v-for="(food) in item.foods" :key="food.item_id"> <div class="food-pic"> <img src="https://upload.jianshu.io/users/upload_avatars/16175630/e2ee85e5-7cb0-429d-a517-bb1c6f1833e4?imageMogr2/auto-orient/strip|imageView2/1/w/80/h/80/format/webp" alt /> </div> <div class="food-main"> <div class="food-info"> <div class="title">{{food.name}}</div> <div class="info">{{food.applicable_quantity_text}}</div> </div> <div class="money">¥{{food.specfoods[0].price}}</div> </div> <div class="food-action"> <div class="action-item minus" v-if="shopcart[food.item_id]" @click="handleMinus(food)">-</div> <div class="action-num" v-if="shopcart[food.item_id]">{{shopcart[food.item_id]}}</div> <div class="action-item puls" @click="handlePuls(food)">+</div> </div> </div> </div> </template> <script> // import { reactive, unref } from 'vue'; import { useStore } from 'vuex'; import { computed } from 'vue'; export default { components: {}, props: { item: Object }, setup() { // store const store = useStore(); // 购物车 const shopcart = computed(() => store.state.shopcart); const handleChangeCount = (food, type) => { const id = food.item_id; const actionName = type > 0 ? 'addItem' : 'subItem'; store.dispatch(actionName, id); }; const handleMinus = food => { handleChangeCount(food, -1); }; const handlePuls = food => { handleChangeCount(food, 1); }; return { shopcart, handleMinus, handlePuls }; } }; </script> <style lang="scss" scoped> ...... </style> 复制代码
SettlementBottom.vue
<template> <div class="SettlementBottom"> <div class="num_box">x{{settlement.count}}</div> <div class="price_box">¥{{settlement.price}}</div> <div class="submit_btn" @click="handleSubmit">结算</div> </div> </template> <script> import { useStore } from 'vuex'; import { computed } from 'vue'; export default { props: {}, setup() { const store = useStore(); const settlement = computed(() => store.getters.settlement); const handleSubmit = () => { const sc = store.state.shopcart; const shopcart = Object.keys(sc).map(key => ({ id: key, count: sc[key] })); console.log('shopcart=>', shopcart); console.log('如果需要原食物的参数可以直接去state中获取'); }; return { settlement, handleSubmit }; } }; </script> <style lang="scss" scoped> ...... </style> 复制代码
github notbucai
notbucai blog
这篇关于Vue3 + Vuex4 构建点餐页面的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-10-04package.json 文件位置在哪?-icode9专业技术文章分享
- 2024-10-01Craco.js学习:从入门到实践指南
- 2024-10-01Create-React-App学习:入门与实践指南
- 2024-10-01CSS-in-JS学习:从入门到实践指南
- 2024-09-30JSX语法学习:从入门到初步掌握
- 2024-09-30Mock.js学习:入门教程与实战演练
- 2024-09-30React Hooks学习:从入门到实践
- 2024-09-30受控组件学习:React中的基础入门教程
- 2024-09-29JS定时器教程:初学者必看指南
- 2024-09-29JS对象教程:初学者的全面指南