代码
This commit is contained in:
commit
a68336073b
10
.eslintrc.js
Normal file
10
.eslintrc.js
Normal file
@ -0,0 +1,10 @@
|
||||
module.exports = {
|
||||
root: true,
|
||||
env: {
|
||||
node: true,
|
||||
},
|
||||
extends: ["plugin:vue/vue3-essential", "eslint:recommended"],
|
||||
parserOptions: {
|
||||
parser: "@babel/eslint-parser",
|
||||
},
|
||||
};
|
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
node_modules
|
||||
package-lock.json
|
||||
dist
|
21
README.md
Normal file
21
README.md
Normal file
@ -0,0 +1,21 @@
|
||||
# vue_cart
|
||||
|
||||
> 使用 Vue 2 脚手架搭建一个简易购物车功能示例
|
||||
|
||||
## Build Setup
|
||||
|
||||
``` bash
|
||||
# install dependencies
|
||||
npm install
|
||||
|
||||
# serve with hot reload at localhost:8080
|
||||
npm run dev
|
||||
|
||||
# build for production with minification
|
||||
npm run build
|
||||
|
||||
# build for production and view the bundle analyzer report
|
||||
npm run build --report
|
||||
```
|
||||
|
||||
For a detailed explanation on how things work, check out the [guide](http://vuejs-templates.github.io/webpack/) and [docs for vue-loader](http://vuejs.github.io/vue-loader).
|
3
babel.config.js
Normal file
3
babel.config.js
Normal file
@ -0,0 +1,3 @@
|
||||
module.exports = {
|
||||
presets: ["@vue/cli-plugin-babel/preset"],
|
||||
};
|
225
config/webpack.config.js
Normal file
225
config/webpack.config.js
Normal file
@ -0,0 +1,225 @@
|
||||
const path = require("path");
|
||||
const ESLintWebpackPlugin = require("eslint-webpack-plugin");
|
||||
const HtmlWebpackPlugin = require("html-webpack-plugin");
|
||||
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
|
||||
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin");
|
||||
const TerserWebpackPlugin = require("terser-webpack-plugin");
|
||||
const CopyPlugin = require("copy-webpack-plugin");
|
||||
const { VueLoaderPlugin } = require("vue-loader");
|
||||
const { DefinePlugin } = require("webpack");
|
||||
const AutoImport = require("unplugin-auto-import/webpack");
|
||||
const Components = require("unplugin-vue-components/webpack");
|
||||
const { ElementPlusResolver } = require("unplugin-vue-components/resolvers");
|
||||
// 需要通过 cross-env 定义环境变量
|
||||
const isProduction = process.env.NODE_ENV === "production";
|
||||
|
||||
const getStyleLoaders = (preProcessor) => {
|
||||
return [
|
||||
isProduction ? MiniCssExtractPlugin.loader : "vue-style-loader",
|
||||
"css-loader",
|
||||
{
|
||||
loader: "postcss-loader",
|
||||
options: {
|
||||
postcssOptions: {
|
||||
plugins: ["postcss-preset-env"],
|
||||
},
|
||||
},
|
||||
},
|
||||
preProcessor && {
|
||||
loader: preProcessor,
|
||||
options:
|
||||
preProcessor === "sass-loader"
|
||||
? {
|
||||
// 自定义主题:自动引入我们定义的scss文件
|
||||
additionalData: `@use "@/styles/element/index.scss" as *;`,
|
||||
}
|
||||
: {},
|
||||
},
|
||||
].filter(Boolean);
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
entry: "./src/main.js",
|
||||
output: {
|
||||
path: isProduction ? path.resolve(__dirname, "../dist") : undefined,
|
||||
filename: isProduction
|
||||
? "static/js/[name].[contenthash:10].js"
|
||||
: "static/js/[name].js",
|
||||
chunkFilename: isProduction
|
||||
? "static/js/[name].[contenthash:10].chunk.js"
|
||||
: "static/js/[name].chunk.js",
|
||||
assetModuleFilename: "static/js/[hash:10][ext][query]",
|
||||
clean: true,
|
||||
},
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.css$/,
|
||||
use: getStyleLoaders(),
|
||||
},
|
||||
{
|
||||
test: /\.less$/,
|
||||
use: getStyleLoaders("less-loader"),
|
||||
},
|
||||
{
|
||||
test: /\.s[ac]ss$/,
|
||||
use: getStyleLoaders("sass-loader"),
|
||||
},
|
||||
{
|
||||
test: /\.styl$/,
|
||||
use: getStyleLoaders("stylus-loader"),
|
||||
},
|
||||
{
|
||||
test: /\.(png|jpe?g|gif|svg)$/,
|
||||
type: "asset",
|
||||
parser: {
|
||||
dataUrlCondition: {
|
||||
maxSize: 10 * 1024,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
test: /\.(ttf|woff2?)$/,
|
||||
type: "asset/resource",
|
||||
},
|
||||
{
|
||||
test: /\.(jsx|js)$/,
|
||||
include: path.resolve(__dirname, "../src"),
|
||||
loader: "babel-loader",
|
||||
options: {
|
||||
cacheDirectory: true,
|
||||
cacheCompression: false,
|
||||
plugins: [
|
||||
// "@babel/plugin-transform-runtime" // presets中包含了
|
||||
],
|
||||
},
|
||||
},
|
||||
// vue-loader不支持oneOf
|
||||
{
|
||||
test: /\.vue$/,
|
||||
loader: "vue-loader", // 内部会给vue文件注入HMR功能代码
|
||||
options: {
|
||||
// 开启缓存
|
||||
cacheDirectory: path.resolve(
|
||||
__dirname,
|
||||
"node_modules/.cache/vue-loader"
|
||||
),
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
plugins: [
|
||||
new ESLintWebpackPlugin({
|
||||
context: path.resolve(__dirname, "../src"),
|
||||
exclude: "node_modules",
|
||||
cache: true,
|
||||
cacheLocation: path.resolve(
|
||||
__dirname,
|
||||
"../node_modules/.cache/.eslintcache"
|
||||
),
|
||||
}),
|
||||
new HtmlWebpackPlugin({
|
||||
template: path.resolve(__dirname, "../public/index.html"),
|
||||
}),
|
||||
new CopyPlugin({
|
||||
patterns: [
|
||||
{
|
||||
from: path.resolve(__dirname, "../public"),
|
||||
to: path.resolve(__dirname, "../dist"),
|
||||
toType: "dir",
|
||||
noErrorOnMissing: true,
|
||||
globOptions: {
|
||||
ignore: ["**/index.html"],
|
||||
},
|
||||
info: {
|
||||
minimized: true,
|
||||
},
|
||||
},
|
||||
],
|
||||
}),
|
||||
isProduction &&
|
||||
new MiniCssExtractPlugin({
|
||||
filename: "static/css/[name].[contenthash:10].css",
|
||||
chunkFilename: "static/css/[name].[contenthash:10].chunk.css",
|
||||
}),
|
||||
new VueLoaderPlugin(),
|
||||
new DefinePlugin({
|
||||
__VUE_OPTIONS_API__: "true",
|
||||
__VUE_PROD_DEVTOOLS__: "false",
|
||||
}),
|
||||
// 按需加载element-plus组件样式
|
||||
AutoImport({
|
||||
resolvers: [ElementPlusResolver()],
|
||||
}),
|
||||
Components({
|
||||
resolvers: [
|
||||
ElementPlusResolver({
|
||||
importStyle: "sass", // 自定义主题
|
||||
}),
|
||||
],
|
||||
}),
|
||||
].filter(Boolean),
|
||||
optimization: {
|
||||
minimize: isProduction,
|
||||
// 压缩的操作
|
||||
minimizer: [
|
||||
new CssMinimizerPlugin(),
|
||||
new TerserWebpackPlugin(),
|
||||
],
|
||||
splitChunks: {
|
||||
chunks: "all",
|
||||
cacheGroups: {
|
||||
// layouts通常是admin项目的主体布局组件,所有路由组件都要使用的
|
||||
// 可以单独打包,从而复用
|
||||
// 如果项目中没有,请删除
|
||||
/*layouts: {
|
||||
name: "layouts",
|
||||
test: path.resolve(__dirname, "../src/layouts"),
|
||||
priority: 40,
|
||||
},*/
|
||||
// 如果项目中使用element-plus,此时将所有node_modules打包在一起,那么打包输出文件会比较大。
|
||||
// 所以我们将node_modules中比较大的模块单独打包,从而并行加载速度更好
|
||||
// 如果项目中没有,请删除
|
||||
elementUI: {
|
||||
name: "chunk-elementPlus",
|
||||
test: /[\\/]node_modules[\\/]_?element-plus(.*)/,
|
||||
priority: 30,
|
||||
},
|
||||
// 将vue相关的库单独打包,减少node_modules的chunk体积。
|
||||
vue: {
|
||||
name: "vue",
|
||||
test: /[\\/]node_modules[\\/]vue(.*)[\\/]/,
|
||||
chunks: "initial",
|
||||
priority: 20,
|
||||
},
|
||||
libs: {
|
||||
name: "chunk-libs",
|
||||
test: /[\\/]node_modules[\\/]/,
|
||||
priority: 10, // 权重最低,优先考虑前面内容
|
||||
chunks: "initial",
|
||||
},
|
||||
},
|
||||
},
|
||||
runtimeChunk: {
|
||||
name: (entrypoint) => `runtime~${entrypoint.name}`,
|
||||
},
|
||||
},
|
||||
resolve: {
|
||||
extensions: [".vue", ".js", ".json"],
|
||||
alias: {
|
||||
// 路径别名
|
||||
"@": path.resolve(__dirname, "../src"),
|
||||
},
|
||||
},
|
||||
devServer: {
|
||||
open: true,
|
||||
host: "localhost",
|
||||
port: 3000,
|
||||
hot: true,
|
||||
compress: true,
|
||||
historyApiFallback: true, // 解决vue-router刷新404问题
|
||||
},
|
||||
mode: isProduction ? "production" : "development",
|
||||
devtool: isProduction ? "source-map" : "cheap-module-source-map",
|
||||
performance: false,
|
||||
};
|
52
package.json
Normal file
52
package.json
Normal file
@ -0,0 +1,52 @@
|
||||
{
|
||||
"name": "vue_cart",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"main": "main.js",
|
||||
"scripts": {
|
||||
"start": "npm run dev",
|
||||
"dev": "cross-env NODE_ENV=development webpack serve --config ./config/webpack.config.js",
|
||||
"build": "cross-env NODE_ENV=production webpack --config ./config/webpack.config.js"
|
||||
},
|
||||
"keywords": [],
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.17.10",
|
||||
"@babel/eslint-parser": "^7.17.0",
|
||||
"@vue/cli-plugin-babel": "^5.0.4",
|
||||
"babel-loader": "^8.2.5",
|
||||
"copy-webpack-plugin": "^10.2.4",
|
||||
"cross-env": "^7.0.3",
|
||||
"css-loader": "^6.7.1",
|
||||
"css-minimizer-webpack-plugin": "^3.4.1",
|
||||
"eslint-plugin-vue": "^8.7.1",
|
||||
"eslint-webpack-plugin": "^3.1.1",
|
||||
"html-webpack-plugin": "^5.5.0",
|
||||
"less-loader": "^10.2.0",
|
||||
"mini-css-extract-plugin": "^2.6.0",
|
||||
"postcss-preset-env": "^7.5.0",
|
||||
"sass": "^1.52.3",
|
||||
"sass-loader": "^12.6.0",
|
||||
"stylus-loader": "^6.2.0",
|
||||
"unplugin-auto-import": "^0.8.8",
|
||||
"unplugin-vue-components": "^0.19.6",
|
||||
"vue-loader": "^17.0.0",
|
||||
"vue-style-loader": "^4.1.3",
|
||||
"vue-template-compiler": "^2.6.14",
|
||||
"webpack": "^5.72.0",
|
||||
"webpack-cli": "^4.9.2",
|
||||
"webpack-dev-server": "^4.9.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"element-plus": "^2.2.6",
|
||||
"vue": "^3.2.33",
|
||||
"vue-router": "^4.0.15",
|
||||
"vuex": "^4.0.2"
|
||||
},
|
||||
"browserslist": [
|
||||
"last 2 version",
|
||||
"> 1%",
|
||||
"not dead"
|
||||
]
|
||||
}
|
17
public/index.html
Normal file
17
public/index.html
Normal file
@ -0,0 +1,17 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1.0">
|
||||
<link rel="icon" href="<%= htmlWebpackPlugin.options.url %>favicon.ico">
|
||||
<title>hello-world</title>
|
||||
</head>
|
||||
<body>
|
||||
<noscript>
|
||||
<strong>We're sorry but hello-world doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
|
||||
</noscript>
|
||||
<div id="app"></div>
|
||||
<!-- built files will be auto injected -->
|
||||
</body>
|
||||
</html>
|
25
src/App.vue
Normal file
25
src/App.vue
Normal file
@ -0,0 +1,25 @@
|
||||
<template>
|
||||
<div id="app">
|
||||
<h1>购物车示例</h1>
|
||||
<p>账号: {{email}}</p>
|
||||
<hr>
|
||||
<h2>产品</h2>
|
||||
<ProductList/>
|
||||
<hr>
|
||||
<ShoppingCart/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapState } from 'vuex'
|
||||
import ProductList from './components/ProductList.vue'
|
||||
import ShoppingCart from './components/ShoppingCart.vue'
|
||||
import 'element-plus/es/components/button/style/css'
|
||||
|
||||
export default {
|
||||
computed: mapState({
|
||||
email: state => state.userInfo.email
|
||||
}),
|
||||
components: { ProductList, ShoppingCart }
|
||||
}
|
||||
</script>
|
23
src/api/shop.js
Normal file
23
src/api/shop.js
Normal file
@ -0,0 +1,23 @@
|
||||
/**
|
||||
* Mocking client-server processing
|
||||
*/
|
||||
const _products = [
|
||||
{"id": 1, "title": "华为 Mate 20", "price": 3999, "inventory": 2},
|
||||
{"id": 2, "title": "小米 9", "price": 2999, "inventory": 0},
|
||||
{"id": 3, "title": "OPPO R17", "price": 2999, "inventory": 5}
|
||||
]
|
||||
|
||||
export default {
|
||||
getProducts (cb) {
|
||||
setTimeout(() => cb(_products), 100)
|
||||
},
|
||||
|
||||
buyProducts (products, cb, errorCb) {
|
||||
setTimeout(() => {
|
||||
// simulate random checkout failure.
|
||||
Math.random() > 0.5
|
||||
? cb()
|
||||
: errorCb()
|
||||
}, 100)
|
||||
}
|
||||
}
|
48
src/components/ProductList.vue
Normal file
48
src/components/ProductList.vue
Normal file
@ -0,0 +1,48 @@
|
||||
<template>
|
||||
<ul>
|
||||
<li
|
||||
v-for="product in products"
|
||||
:key="product.id">
|
||||
{{ product.title }} - {{ product.price }} x {{ product.inventory }}
|
||||
<br>
|
||||
<el-input-number v-if="product.inventory" :min="1" :max="product.inventory" v-model="preSelectProducts[product.id]" />
|
||||
<el-input-number v-else :disabled="true" />
|
||||
<el-button
|
||||
:disabled="!product.inventory"
|
||||
@click="addProductToCart({ product: product, num: preSelectProducts[product.id] })">
|
||||
加入购物车
|
||||
</el-button>
|
||||
</li>
|
||||
</ul>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapState, mapActions } from 'vuex'
|
||||
import { ElButton } from 'element-plus'
|
||||
|
||||
export default {
|
||||
components: { ElButton },
|
||||
computed: {
|
||||
...mapState({
|
||||
products: state => state.products.all,
|
||||
preSelectProducts: state => state.cart.preSelectProducts
|
||||
})
|
||||
},
|
||||
// computed: {
|
||||
// products(){
|
||||
// return this.$store.state.products.all
|
||||
// }
|
||||
// },
|
||||
methods: mapActions('cart', [
|
||||
'addProductToCart'
|
||||
]),
|
||||
// methods: {
|
||||
// addProductToCart(product){
|
||||
// this.$store.dispatch('cart/addProductToCart', product)
|
||||
// }
|
||||
// },
|
||||
created () {
|
||||
this.$store.dispatch('products/getAllProducts');
|
||||
}
|
||||
}
|
||||
</script>
|
54
src/components/ShoppingCart.vue
Normal file
54
src/components/ShoppingCart.vue
Normal file
@ -0,0 +1,54 @@
|
||||
<template>
|
||||
<div class="cart">
|
||||
<h2>清单</h2>
|
||||
<p v-show="!products.length"><i>请添加产品到购物车</i></p>
|
||||
<ul>
|
||||
<li
|
||||
v-for="product in products"
|
||||
:key="product.id">
|
||||
{{ product.title }} - {{ product.price }} x {{ product.quantity }}
|
||||
</li>
|
||||
</ul>
|
||||
<p>合计: {{ total }}</p>
|
||||
<p><el-button type="primary" :disabled="!products.length" @click="checkout(products)">提交</el-button></p>
|
||||
<p v-show="checkoutStatus">提交 {{ checkoutStatus }}.</p>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapGetters, mapState } from 'vuex'
|
||||
import { ElButton } from 'element-plus'
|
||||
|
||||
export default {
|
||||
components: { ElButton },
|
||||
computed: {
|
||||
...mapState({
|
||||
checkoutStatus: state => state.cart.checkoutStatus
|
||||
}),
|
||||
...mapGetters('cart', {
|
||||
products: 'cartProducts',
|
||||
total: 'cartTotalPrice'
|
||||
}),
|
||||
// ...mapGetters({
|
||||
// products: 'cart/cartProducts',
|
||||
// total: 'cart/cartTotalPrice'
|
||||
// })
|
||||
},
|
||||
// computed: {
|
||||
// checkoutStatus(){
|
||||
// return this.$store.state.cart.checkoutStatus
|
||||
// },
|
||||
// products() {
|
||||
// return this.$store.getters['cart/cartProducts']
|
||||
// },
|
||||
// total() {
|
||||
// return this.$store.getters['cart/cartTotalPrice']
|
||||
// }
|
||||
// },
|
||||
methods: {
|
||||
checkout (products) {
|
||||
this.$store.dispatch('cart/checkout', products)
|
||||
}
|
||||
},
|
||||
}
|
||||
</script>
|
5
src/main.js
Normal file
5
src/main.js
Normal file
@ -0,0 +1,5 @@
|
||||
import { createApp } from "vue";
|
||||
import store from "./store"
|
||||
import App from "./App";
|
||||
|
||||
createApp(App).use(store).mount(document.getElementById("app"));
|
17
src/store/index.js
Normal file
17
src/store/index.js
Normal file
@ -0,0 +1,17 @@
|
||||
import { createStore } from 'vuex'
|
||||
import cart from './modules/cart'
|
||||
import products from './modules/products'
|
||||
|
||||
export default createStore({
|
||||
state () {
|
||||
return {
|
||||
userInfo: {
|
||||
email: "xxxxxx@qq.com"
|
||||
}
|
||||
};
|
||||
},
|
||||
modules: {
|
||||
cart,
|
||||
products
|
||||
},
|
||||
})
|
101
src/store/modules/cart.js
Normal file
101
src/store/modules/cart.js
Normal file
@ -0,0 +1,101 @@
|
||||
import shop from '../../api/shop'
|
||||
import { CART, PRODUCTS } from '../mutation-types'
|
||||
|
||||
// initial state
|
||||
// shape: [{ id, quantity }]
|
||||
const state = {
|
||||
// 购物车商品列表数据
|
||||
items: [],
|
||||
// 用于存放要加入购物车的商品跟数量的对应关系
|
||||
preSelectProducts: {},
|
||||
// 标记购买状态
|
||||
checkoutStatus: null
|
||||
}
|
||||
|
||||
// getters
|
||||
const getters = {
|
||||
cartProducts: (state, getters, rootState) => {
|
||||
return state.items.map(({ id, quantity }) => {
|
||||
const product = rootState.products.all.find(product => product.id === id)
|
||||
return {
|
||||
title: product.title,
|
||||
price: product.price,
|
||||
quantity
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
cartTotalPrice: (state, getters) => {
|
||||
return getters.cartProducts.reduce((total, product) => {
|
||||
return total + product.price * product.quantity
|
||||
}, 0)
|
||||
}
|
||||
}
|
||||
|
||||
// actions
|
||||
const actions = {
|
||||
checkout ({ commit, state }, products) {
|
||||
const savedCartItems = [...state.items]
|
||||
commit(CART.SET_CHECKOUT_STATUS, null)
|
||||
// empty cart
|
||||
commit(CART.SET_CART_ITEMS, { items: [] })
|
||||
shop.buyProducts(
|
||||
products,
|
||||
() => commit(CART.SET_CHECKOUT_STATUS, 'successful'),
|
||||
() => {
|
||||
commit(CART.SET_CHECKOUT_STATUS, 'failed')
|
||||
// rollback to the cart saved before sending the request
|
||||
commit(CART.SET_CART_ITEMS, { items: savedCartItems })
|
||||
}
|
||||
)
|
||||
},
|
||||
|
||||
addProductToCart ({ state, commit }, { product, num} ) {
|
||||
num = num < 1 ? 1 : num;
|
||||
num = num > product.inventory ? product.inventory : num;
|
||||
commit(CART.SET_CHECKOUT_STATUS, null)
|
||||
|
||||
if (product.inventory > 0) {
|
||||
const cartItem = state.items.find(item => item.id === product.id)
|
||||
if (!cartItem) {
|
||||
commit(CART.PUSH_PRODUCT_TO_CART, { id: product.id, num: num })
|
||||
} else {
|
||||
commit(CART.INCREMENT_ITEM_QUANTITY, { id: cartItem.id, num: num })
|
||||
}
|
||||
// remove 1 item from stock
|
||||
commit(`products/${PRODUCTS.DECREMENT_PRODUCT_INVENTORY}`, { id: product.id, num: num }, { root: true })
|
||||
state.preSelectProducts[product.id] = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// mutations
|
||||
const mutations = {
|
||||
[CART.PUSH_PRODUCT_TO_CART] (state, { id, num }) {
|
||||
state.items.push({
|
||||
id,
|
||||
quantity: Number(num)
|
||||
})
|
||||
},
|
||||
|
||||
[CART.INCREMENT_ITEM_QUANTITY] (state, { id, num }) {
|
||||
const cartItem = state.items.find(item => item.id === id)
|
||||
cartItem.quantity += Number(num)
|
||||
},
|
||||
|
||||
[CART.SET_CART_ITEMS] (state, { items }) {
|
||||
state.items = items
|
||||
},
|
||||
|
||||
[CART.SET_CHECKOUT_STATUS] (state, status) {
|
||||
state.checkoutStatus = status
|
||||
}
|
||||
}
|
||||
|
||||
export default {
|
||||
namespaced: true,
|
||||
state,
|
||||
getters,
|
||||
actions,
|
||||
mutations
|
||||
}
|
43
src/store/modules/products.js
Normal file
43
src/store/modules/products.js
Normal file
@ -0,0 +1,43 @@
|
||||
import shop from '../../api/shop'
|
||||
import {PRODUCTS} from '../mutation-types'
|
||||
|
||||
// initial state
|
||||
const state = {
|
||||
// 商品列表
|
||||
all: []
|
||||
}
|
||||
|
||||
// getters
|
||||
const getters = {}
|
||||
|
||||
// actions
|
||||
const actions = {
|
||||
getAllProducts ({ commit, rootState }) {
|
||||
shop.getProducts(products => {
|
||||
for (let product of products) {
|
||||
rootState.cart.preSelectProducts = Object.assign({}, rootState.cart.preSelectProducts, { [product.id]: 1 });
|
||||
}
|
||||
commit(PRODUCTS.SET_PRODUCTS, products)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// mutations
|
||||
const mutations = {
|
||||
[PRODUCTS.SET_PRODUCTS] (state, products) {
|
||||
state.all = products
|
||||
},
|
||||
|
||||
[PRODUCTS.DECREMENT_PRODUCT_INVENTORY] (state, { id, num }) {
|
||||
const product = state.all.find(product => product.id === id)
|
||||
product.inventory -= Number(num)
|
||||
}
|
||||
}
|
||||
|
||||
export default {
|
||||
namespaced: true,
|
||||
state,
|
||||
getters,
|
||||
actions,
|
||||
mutations
|
||||
}
|
11
src/store/mutation-types.js
Normal file
11
src/store/mutation-types.js
Normal file
@ -0,0 +1,11 @@
|
||||
export const CART = {
|
||||
PUSH_PRODUCT_TO_CART: 'pushProductToCart',
|
||||
INCREMENT_ITEM_QUANTITY: 'incrementItemQuantity',
|
||||
SET_CART_ITEMS: 'setCartItems',
|
||||
SET_CHECKOUT_STATUS: 'setCheckoutStatus'
|
||||
}
|
||||
|
||||
export const PRODUCTS = {
|
||||
SET_PRODUCTS:'setProducts',
|
||||
DECREMENT_PRODUCT_INVENTORY: 'decrementProductInventory'
|
||||
}
|
7
src/styles/element/index.scss
Normal file
7
src/styles/element/index.scss
Normal file
@ -0,0 +1,7 @@
|
||||
@forward 'element-plus/theme-chalk/src/common/var.scss' with (
|
||||
$colors: (
|
||||
'primary': (
|
||||
'base': green,
|
||||
),
|
||||
),
|
||||
);
|
Loading…
Reference in New Issue
Block a user