zoukankan      html  css  js  c++  java
  • vue学习日记05

    vuex

     

    例如创建一个min-vuex.js

    import Vue from 'vue'
    const Store = function Store (options = {}) {
        const {state = {} , mutations ={}} = options
        this._vm = new Vue ({
            data : {
                $$state: state
            }
        })this._mutations = mutations
    }
    Store.prototype.commit = function (type, payload) {
        if(this._mutations[type]) {
            this._mutations[type](this.state, payload)
        }
    }
    Object.defineProperties(Store.prototype, {
        state: {
            get: function() {
                return this._vm._data.$$state
            }
        }
    })
    
    export default {Store}

    import Vue from 'vue'
    import App from './App'
    import router from './router'
    import Vuex from './min-vuex'
    
    Vue.config.productionTip = false
    
    const store = new Vuex.Store({
      state: {
        count : 0
      },
      mutations: {
        increment (state, n) {
          state.count += n
        }
      }
    })
    /* eslint-disable no-new */
    Vue.prototype.$store = store 
    
    new Vue({
      el: '#app',
      router,
      components: { App },
      template: '<App/>'
    })

    https://www.jianshu.com/p/d95a7b8afa06 这篇文章有工作原理解释。

    我们在使用vuex的时候,官方还提供了一些辅助函数。如 mapState, mapGetter,mapActions。

    mapState:

     假如我们在计算属性中返回state里的值,普通用法就需要返回很多个,用辅助函数就可以缩写,以mapState为例

    // 先引入
    import { mapState, mapActions } from 'vuex'
     
     
    // 普通用法
    computed: {     
     products(){
          return this.$store.state.products.all
        }
      },
     
     // mapState 辅助函数用法
      computed: mapState({  
        products: state => state.products.all,
      }),
     
     //如果state的名称与你计算属性名称相同,可以传一个字符串数组
      computed: mapState(['products']),
     
      //如果该组件还存在其他计算属性
      computed: {    
        ...mapState({
          products: state => state.products.all,
        }),
        other() {
          return 'other computed'
        }
      }

    其他函数也大致相同,目的就是简化一些 this.$store.state之类的操作。

    Module

      官网例子:

      

      由此可见,每个module都有自己单独的state,mutations,actions,getters。

      但是如果,在每个module的mutations或actons中,存在有一样名字的函数,如每个模块中都包含 setName的actions,我们在调用 this.$store.dispatch('setName‘) 的时候,

      所有模块中的同名actions都会被执行。因此若要避免这个情况,我们就需要给每个actions单独命名,或者给每个模块使用上命名空间。

    // moduleA.js
    const state = {   ...... } // getters const getters = {   ...... } // actions const actions = {   ...... } // mutations const mutations = {   ...... } export default { namespaced: true, state, getters, actions, mutations }

    这个时候我们调用的话,就需要加上命名空间的字段 this.$store.dispatch('moduleA/....'),同时mapState等也有的同样的改变。

     computed: {
      ...mapState("moduleA",{
       useName: state => state.useName
      }),
      ...mapGetters("moduleA", ["userName"])
     },

     在使用了命名空间之后,每个模块中的getters会产生第三个参数,rootState作为根数据。数据格式是一个对象,然后每个模块的state都是该对象中的一个属性,值也是一个对象,包含该模块的state数据。

    一个具体例子:

    目录结构:

    //  cart.js
    import shop from '../../api/shop' import { CART, PRODUCTS } from '../mutations-types' // initial state // shape: [{ id, quantity }] const state = { items: [], 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) console.log(rootState.products.all,'....111.') 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 }) } ) }, setName ({state,commit,rootState}) { commit('cartSetName',rootState.userInfo) }, addProductToCart ({ state, commit }, product) { 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 }) } else { commit(CART.INCREMENT_ITEM_QUANTITY, cartItem) } // remove 1 item from stock commit(`products/${PRODUCTS.DECREMENT_PRODUCT_INVENTORY}`, { id: product.id }, { root: true }) } } } // mutations const mutations = { [CART.PUSH_PRODUCT_TO_CART] (state, { id }) { state.items.push({ id, quantity: 1 }) }, [CART.INCREMENT_ITEM_QUANTITY] (state, { id }) { const cartItem = state.items.find(item => item.id === id) cartItem.quantity++ }, [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 }
    // products.js
    import shop from '../../api/shop' import {PRODUCTS} from '../mutations-types' // initial state const state = { all: [] } // getters const getters = {} // actions const actions = { getAllProducts ({ commit }) { shop.getProducts(products => { commit(PRODUCTS.SET_PRODUCTS, products) }) } } // mutations const mutations = { [PRODUCTS.SET_PRODUCTS] (state, products) { state.all = products }, [PRODUCTS.DECREMENT_PRODUCT_INVENTORY] (state, { id }) { const product = state.all.find(product => product.id === id) product.inventory-- } } export default { namespaced: true, state, getters, actions, mutations }
    // index.js
    import Vue from 'vue'
    import Vuex from 'vuex'
    import cart from './modules/cart'
    import products from './modules/porducts'
    
    Vue.use(Vuex)
    export default new Vuex.Store({
      state: {
        userInfo: {
          email: "wl"
        }
      },
      modules: {
        cart,
        products
      },
    })
    // mutations-types.js
    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' }

    组件代码

    主页:

    <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 './day04_components/products'
    import ShoppingCart from './day04_components/shoppingCart'
    export default {
      computed: mapState({
        email: state => state.userInfo.email
      }),
      components: { ProductList, ShoppingCart },
    }
    </script>

    清单:

    <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><button :disabled="!products.length" @click="checkout(products)">提交</button></p>
        <p v-show="checkoutStatus">提交 {{ checkoutStatus }}.</p>
      </div>
    </template>
    
    <script>
    import { mapGetters, mapState } from 'vuex'
    export default {
      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>

    产品列表:

    <template>
      <ul>
        <li
          v-for="product in products"
          :key="product.id">
          {{ product.title }} - {{ product.price }}
          <br>
          <button
            :disabled="!product.inventory"
            @click="addProductToCart(product)">
            加入购物车
          </button>
        </li>
      </ul>
    </template>
    
    <script>
    import { mapState, mapActions } from 'vuex'
    export default {
      computed: mapState({
        products: state => state.products.all,
      }),
      // 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>

    模拟数据:

    const _products = [
        {"id": 1, "title": "华为 Mate 20", "price": 3999, "inventory": 2},
        {"id": 2, "title": "小米 9", "price": 2999, "inventory": 1},
        {"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)
        }
      }

    效果图:

    a

  • 相关阅读:
    JS 获取本月第一天零点时间戳并转化成yy-mm-dd
    JS 两个对象数组合并并去重
    element ui datePicker 设置当前日期之前的日期不可选
    整理一些vue elementui 问题 + 链接方法
    css 修改placeholder的颜色
    js循环内0.5s停止
    自定义border 为 dashed 时的虚线间距
    如何让浮动元素水平/垂直居中
    centos7.6设置sftp服务
    HikariCP Druid比较
  • 原文地址:https://www.cnblogs.com/wangnothings/p/12421457.html
Copyright © 2011-2022 走看看