项目地址 https://github.com/bolonotlob...
方法一:vue
.router-link-exact-active
<!--App.vue--> <template> <div class="app"> <div class="nav"> <router-link tag="li" to="/home">Home</router-link> <router-link tag="li" to="/market">Market</router-link> <router-view></router-view> </div> </div> </template> <script> export default {}; </script> <style scoped > .nav li.router-link-exact-active { // 高亮 color: red; } </style>
方法二:ios
linkActiveClass:个人样式名
git
//router/index.js const routes = [ { path: '/', redirect: '/home' }, { path: '/home',component: ()=>import('@/views/Home')}, { path: '/market',component: ()=> import('@/views/Market')} ] const router = new VueRouter({ linkActiveClass: 'myactive', // .myactive 为路由激活样式名,在 App.vue 中定义 .myactive{ color: red; } routes })
根目录/vue.config.jsgithub
const products = [ { id: 1, name: 'iphone', price: 800, inventory: 10 }, { id: 2, name: 'iphone pro', price: 1000, inventory: 10 }, { id: 3, name: 'iphone max', price: 1200, inventory: 10 }, ] module.exports = { devServer: { before(app, serve) { app.get('/api/products', (req, res) => { res.json({ result: products }) }) } } }
http://localhost:8080/api/products
访问数据const store = new Vuex.Store({ // ... strict: true }) /* 在严格模式下,不管什么时候发生了状态变动且不是由 mutation函数引发的, 将会抛出错误。这能保证全部的状态变动都能被调试工具跟踪到 */
/* ---apis |---apis.js |---index.js */ // apis.js export default { baseUrl: 'http://localhost:8080/api', getAllProducts: '/products' } // index.js import apis from './apis' import axios from 'axios' const ajax = axios.create({ baseURL:apis.baseUrl }) export const getAllProducts = ()=> ajax.get(apis.getAllProducts)
import * as service from '@/apis/index.js' actions: { async getAllProducts({ commit }) { // 发起请求获取商品数据 try { const ret = await service.getAllProducts() if (ret.status === 200) { const products = ret.data.result commit('SET_PRODUCTS',products) } } catch (err) { console.log(err) } } }
这里咱们只把商品id和数量存入cartList,固然也能够存整个商品对象(这里不这么作)ajax
//store/modules/products.js mutations: { ADD_TO_CART: (state, { id, quantity }) => { state.cartList.push({ id, quantity }) }, INCREMENT_QUANTITY: (state, { id }) => { state.cartList.find(v => v.id === id).quantity++ } }, actions: { addToCart({ commit, state }, product) { console.log('addToCart') // 判断购物车中是否已经存在 const cartItem = state.cartList.find(v => v.id === product.id) if (cartItem) { // 若是有 commit('INCREMENT_QUANTITY', { id: product.id }) } else { // 没有 commit('ADD_TO_CART', { id: product.id, quantity: 1 }) } } }
//store/modules/cart.js getters: { getCartListInfo: (state, getters, rootState) => { return state.cartList.map(({ id, quantity }) => { const product = rootState.products.products.find(v => v.id === id) return { id, name: product.name, price: product.price, quantity } }) } },
// store/modules/cart.js getTotalPrice: (state, getters) => { return getters.getCartListInfo.reduce((total, item) => { return total + item.price * item.quantity }, 0) }
//cart.js 提交 mutations 到 products.js // 全局命名空间提交 mutations 须要加上 {root: true} commit('products/DECREMENT_INVENTORY', { id: product.id }, { root: true })
// main.js Vue.filter('currency', v => '$' + v)
当触发 Actions,会把父模块和子模块的都触发vuex
官方: 默认状况下,模块内部的 action、mutation 和 getter 是注册在全局命名空间的——这样使得多个模块可以对同一 mutation 或 action 做出响应。
/* --- store |---index.js |---modules |---products.js |---cart.js */ // index.js actions getAllProducts(){ console.log(111) } // products.js actions getAllProducts(){ console.log(222) } // Products.vue 组件 dispatch created(){ this.$store.dispatch('getAllProducts') } // 结果分析 // 咱们products 没有使用命名空间(namespaced:true) 时,这两个都会触发 // 输出结果: // 111 // 222 // 咱们给 products.js 加上命名空间 // namespaced: true, // 组件Products.vue dispatch created(){ this.$store.dispatch('products/getAllProducts') }
// store/index.js state: { products: [1,2] } // store/modules/products.js state: { prodcuts:[3,4] } // 组件中获取 computed: { ...mapState(['products']) // [3,4] } // vuex.esm.js?2f62:721 [vuex] state field "products" was overridden by a module with the same name at "products"
mapState 的参数json
// 1 computed: { products(){ return this.$store.state.products.products } } // 2 函数形式 state做为形参传入 computed: mapState({ /** products(state){ return state.products.products } */ products:state=>state.products.products }) // 3 对象形式 computed: mapState({ products:'products' }) // 4 展开运算 ...mapState computed: { ...mapState('products',['products']) // ...mapState('命名空间',对象/数组) }
this.$store.dispatch(命名空间/actions中方法名)axios
this.$store.dispatch('cart/addToCart')
// cart.vue created() { // 经过 localStorage 初始化购物车 this.$store.dispatch("cart/initializeCartList"); } // products.vue created() { // 若是localStorage 有就直接从里面拿,没有再去服务器取 this.$store.dispatch("products/getAllProducts"); }, // 出现的问题: /* 当时没注意,products.js 里面用的是mounted 去 dispatch 的 而 cart.js 里面是 created() 就 dispatch 了 而 cart.js 的 getters里面返回商品信息的时候须要根据 cartList 的 id,去查询 products 里面商品的price,name 这些属性。 那这个时候由于 生命周期的顺序 created 在 mounted 以前(虽然不一样组件, 并不能保证 cart组件的 created 必定在 products 组件的 mounted 以前) cart 组件 created 时拿到了数据更新了 cartList,getters重新开始计算(像计算属性), 可是这个时候 products 没有拿回来数据,全部 getCartListInfo 里面会出现 product的 属性没有定义会报错 error: Cannot read property 'name' of undefined" */ // cart.js getters: { getCartListInfo: (state, getters, rootState) => { return state.cartList.map(({ id, quantity }) => { const product = rootState.products.products.find(v => v.id === id) return { id, name: product.name, price: product.price, quantity } }) } }
如何解决这个问题呢?后端
let products = JSON.parse(localStorage.getItem('products')) if (products) { commit('SET_PRODUCTS', products) // 在这里去dispatch // 先拿到 products 再去拿 cartList dispatch('cart/initializeCartList',null,{root:true}) }
// 有命名空间时 commit ,dispatch, 全局分发,...mapState this.$store.dispatch("products/getAllProducts"); this.$store.commit("cart/ADD_TO_CART") commit('products/DECREMENT_INVENTORY', { id: product.id }, { root: true }) //全局分发 mapState(namespace?: string, map: Array<string> | Object<string | function>): Object