uni-app中应用vuex示例

uni-app是当前前端开端多端应用的一个强大的工具,可以同时七端发布。由于之前前端的功能较简单,所以前端一般不重视程序架构设计,通常所说的MVVM等架构,一般也就止步于VUE就是基于MVVM,使用VUE就是采用MVVM架构,而实际上采用架构的作用,就是要使应用代码职责分离,增加可维护性。在本篇博文中,我将向大家展示,怎样通过使用VUEX,将业务逻辑代码由.vue文件中抽取出来,形成一个职责清晰的应用架构。

整体架构

我们首先来看一下程序的整体架构:
在这里插入图片描述
如上图所示,我们在store中保存vuex的store定义,以及store下的模块定义。在pages里面是页面*.vue文件,components中是我们页面将要使用的组件,这里定义了两个组件:cart和products,分别用来显示购物车和商品列表,api下保存与后台接口交互的模块,这里定义的是shop。

全局引用vuex

我们首先在main.js引入vuex的总store:

....................................
import store from './store'
....................................
const app = new Vue({
	store,
    ...App
})
...................................

我们在这里定义的store,可以在应用任何页面中引用。

主页面

接着我们定义示例的页面,这个页面引用购物车和商品组件显示相关内容:

<template>
  <div id="app">
    <h3>购物车示例</h3>
    <hr>
    <h5>产品列表</h5>
    <ProductList/>
    <hr>
    <ShoppingCart/>
  </div>
</template>

<script>
import ProductList from '../../components/ProductList.vue'
import ShoppingCart from '../../components/ShoppingCart.vue'
export default {
  components: { ProductList, ShoppingCart }
}
</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>
	  <button @click="test001">测试</button>
	  <button @click="test002">内部</button>
    </li>
  </ul>
</template>

<script>
import { mapState, mapActions } from 'vuex'
export default {
  computed: {
	...mapState({
		products: state => state.products.all
	})
  },
  methods: {
	...mapActions('cart', ['addProductToCart']),
	...mapActions({
		test001: 'products/test001'
	}),
	test002: (e) => {
		console.log('页面内事件')
	}
  },
  created () {
    this.$store.dispatch('products/getAllProducts')
  }
}
</script>

页面用v-for显示商品列表,加入购物车按钮可以调用store.cart模块的addProductToCart,将其加入购物车中;测试按钮显示另外一种方式调用store模块的actions方法,内部按钮显示仅用于页面内事件,无需使用vuex。
在脚本部分,首先引入vuex的mapState和mapActions,虽然有其他方法实现同样任务,但是建议统一使用这种方式。
在计算属性部分,我们将store中products.all属性赋给页面的计算属性products。
在方法部分,我们将加入购物车按钮的响应事件,定义为调用store的cart模块的addProductToCart的actions;将测试按钮的单击响应事件,定义为调用store的products模块的test001的actions;将内部按钮的单击响应事件,定义为调用页面内消息响应函数。在页面创建完成的生命周期函数中,调用store的products模块的getAllProducts的actions。

products模块

接下来我们来看products模块:

import shop from '../../api/shop'

// initial state
const state = {
  all: []
}

// getters
const getters = {}

// actions
const actions = {
  getAllProducts ({ commit }) {
    shop.getProducts(products => {
      commit('setProducts', products)
    })
  },
  test001() {
	  console.log('store.products.test001 is running...')
  }
}

// mutations
const mutations = {
  setProducts (state, products) {
    state.all = products
  },

  decrementProductInventory (state, { id }) {
    const product = state.all.find(product => product.id === id)
    product.inventory--
  }
}

export default {
  namespaced: true,
  state,
  getters,
  actions,
  mutations
}

这里我们看到,其有一个all的属性,就是主页中要显示的商品列表数据。
接下来定义getter方法,这里没有定义。
在接下来是定义actions,当我们要在异步请求中更新store.state时,需要调用actions中的方法,由这些方法调用对应的mutation,而mutation只能是同步调用。例如这里定义的getAllProducts,由于需要调用网络请求,因此是异步的,所以需要在actions里调用mutation方法。大家可以看到,调用shop对应的方法时,参数为一个箭头函数,当API层处理返回函数时,会执行这个箭头函数,在这个箭头函数中调用commit方法,由vuex处理为对mutation方法的调用。
接下来定义mutation方法,该方法去实际更新state中的数据。
我们在getAllProducts中看到,我们要调用api层的shop来实现从后台取商品列表数据的功能,因此我们来看api层的实现。

API层

这一层主要用于处理与后台交互,以getAllProducts为例:

/**
 * Mocking client-server processing
 */
const _products = [
  {"id": 1, "title": "鱼香肉丝", "price": 25.01, "inventory": 20},
  {"id": 2, "title": "宫爆鸡丁", "price": 30.99, "inventory": 10},
  {"id": 3, "title": "剁椒鱼头", "price": 59.99, "inventory": 5}
]

export default {
  getProducts (cb) {
    setTimeout(() => cb(_products), 100)
  },

  buyProducts (products, cb, errorCb) {
    setTimeout(() => {
      // simulate random checkout failure.
      (Math.random() > 0.5 || navigator.userAgent.indexOf('PhantomJS') > -1)
        ? cb()
        : errorCb()
    }, 100)
  }
}

这里为了简化,没有使用Axiox调用网络请求,只使用定时函数,返回一个写死的结果,并调用回调函数,完成整个流程。

发布了204 篇原创文章 · 获赞 1236 · 访问量 124万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章