Vue外卖八:vuex的配置、状态的管理state,修改mutations,提交actions使用、首页的数据逻辑写入、vuex状态读取、1维数组改2维数组

45 篇文章 2 订阅

一、准备:vuex目录/文件构建

vuex文档:https://vuex.vuejs.org/zh/guide/
vuex实操:https://blog.csdn.net/u010132177/article/details/103744554

1.dos命令创建store文件夹/文件src/store

md store
cd store
echo export default{}>actions.js
echo export default{}>getters.js
echo export default{}> index.js
echo export default{}> mutation-types.js
echo export default{}> mutations.js
echo export default{}>state.js

store目录结构共6个文件

store/
	 actions.js
	 getters.js
	 index.js
	 mutation-types.js
	 mutations.js
	 state.js

二、vuex实战:管理代码

vuex各组件关系:

view ->Action(dispatch) ->Mutations(Commit) ->State(Mutate) -> View

1.state.js根据页面需要构建状态

// 所有要管理的状态数据:从页面需求分析出来,最好和api/index.js里的命名相同
export default{
  latitude: 40.10038, // 纬度
  longitude: 116.36867, // 经度
  address: {}, //地址相关信息对象
  categorys: [], // 食品分类数组
  shops: [], // 商家数组
  
  userInfo: {}, // 用户信息
  goods: [], // 商品列表
  ratings: [], // 商家评价列表
  info: {}, // 商家信息
  cartFoods: [], // 购物车中食物的列表
  searchShops: [], // 搜索得到的商家列表
}

2.index.js 把各部分统一到一起,并new一个Vuex.Store对象

import Vue from 'vue'
import Vuex from 'vuex'
import state from './state'
import actions from './actions'
import mutations from './mutations'
import getters from './getters'

Vue.use(Vuex)

export default new Vuex.Store({
	state,
	actions,
	mutations,
	getters
})

3.mutation-types.js 定义mutation常量用于对其动态命名,以方便管理维护

/*
包含n个mutation的type名称常量
 */
export const RECEIVE_ADDRESS = 'receive_address' // 接收地址
export const RECEIVE_CATEGORYS = 'receive_categorys' // 接收食品分类数组
export const RECEIVE_SHOPS = 'receive_shops' // 接收商家数组
export const RECEIVE_USER_INFO = 'receive_user_info' // 接收用户信息
export const RESET_USER_INFO = 'reset_user_info' // 重置用户信息

export const RECEIVE_GOODS = 'receive_goods' // 接收商品数组
export const RECEIVE_RATINGS = 'receive_ratings' // 接收商家评价数组
export const RECEIVE_INFO = 'receive_info' // 接收商家信息

export const INCREMENT_FOOD_COUNT = 'increment_food_count' // 增加food中的count
export const DECREMENT_FOOD_COUNT = 'decrement_food_count' // 减少food中的count
export const CLEAR_CART = 'clear_cart' // 清空购物车

export const RECEIVE_SEARCH_SHOPS = 'receive_search_shops' // 接收搜索的商家数组

4. mutations.js改变状态函数

说明:此处动作为commit

中括号为计算属性名es6语法:作用是动态的写出当前函数名,方便后期维护:[RECEIVE_ADDRESS](state,{address}){state.address=address}
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/Object_initializer#%E8%AE%A1%E7%AE%97%E5%B1%9E%E6%80%A7%E5%90%8D

import {
  RECEIVE_ADDRESS,
  RECEIVE_CATEGORYS,
  RECEIVE_SHOPS,
  RECEIVE_USER_INFO,
  RESET_USER_INFO,
  RECEIVE_INFO,
  RECEIVE_RATINGS,
  RECEIVE_GOODS,
  INCREMENT_FOOD_COUNT,
  DECREMENT_FOOD_COUNT,
  CLEAR_CART,
  RECEIVE_SEARCH_SHOPS
} from './mutation-types.js'

export default{
	//中括号为计算属性名es6语法:作用是动态的写出当前函数名,方便后期维护
	[RECEIVE_ADDRESS](state,{address}){state.address=address},
	[RECEIVE_CATEGORYS](state,{categorys}){state.categorys=categorys},
	[RECEIVE_SHOPS](state,{shops}){state.shops=shops}
  
}

5.actions.js 提交改变状态

关键代码:提交mutation语法 commit(对象名,对象值)
commit(RECEIVE_ADDRESS,{address})

// 控制mutations
import {
  RECEIVE_ADDRESS,
  RECEIVE_CATEGORYS,
  RECEIVE_SHOPS,
} from './mutation-types.js'
import {
  reqAddress,
  reqFoodCategorys,
  reqShops,
} from '../api/index.js'

export default{
	//获取地址用于改变状态
	/* ★★★ ({commit,state})是解构写法相当于:
	原(context.commit,context.state)*/
	async getAddress({commit,state}){
		//构造纬,经度参数用于请求
		const geohash=state.latitude+','+state.longitude
		const result=await reqAddress(geohash)
		// 提交一个状态改变
		if(result.code===0){
			const address=result.data
			//提交mutation,commit(对象名,对象值)
			commit(RECEIVE_ADDRESS,{address})
		}
	},

	//获取食物分类(首页滑动导航)
	async getCategorys({commit}){
		const result=await reqFoodCategorys()
		if(result.code===0){
			const categorys=result.data
			commit(RECEIVE_CATEGORYS,{categorys})
		}
	},

	// 获取商铺列表
	async getShops({commit,state}){
		/*const latitude=state.latitude
		const longitude=state.longitude*/
		const {longitude,latitude}=state
		// 和api里的参数位置要相同经,纬度
		result=await reqShops(longitude,latitude)
		if(result.code===0){
			const shops=result.data
			commit(RECEIVE_SHOPS,{shops})
		}
	}
}

6.main.js挂载vuex

// 入口文件
import Vue from 'vue'
import App from './App'
import router from './router/index.js'
import store from './store' //【1】引入vuex管理状态

// es6写法
new Vue({
	el: '#app',
	render: h => h(App),
	router,
	store //【2】挂载vuex的store
})

7.app.vue试action(dispatch)一次

<script>
...略过
export default {
	//挂载底部组件
	components:{
		FooterGuide
	},
	//【1】试dispatch一次
	mounted(){
	// getAddress来源actions.js
		this.$store.dispatch('getAddress')
	}
}
</script>

7.2(二选一项)actions的dispatch也可用如下方法调用,实现调用时直接用this.getAddress()

<script>
// 2.引入底部组件
import FooterGuide from './components/FooterGuide/FooterGuide.vue'
import {mapActions} from 'vuex' //【1】调用actions方法2:引入辅助函数

export default {
	//3.挂载底部组件
	components:{
		FooterGuide
	},
	mounted(){
		/* 调用actions方法1:getAddress来源actions.js
		this.$store.dispatch('getAddress')*/
		// 【3】调用actions方法2:
		this.getAddress()
	},
	methods:{
		// 【2】调用actions方法2:把getAddress方法解构到当前位置(把getAddress()函数直接复制进来)
		// mapActions() 返回的是一个对象, 
		// 用了 ... 扩展符后,才可以放进一个对象里,
		// 和其他组件内定义的method在同一个methods对象。
		// 参数来自:store/actions.js内的方法
		...mapActions(['getAddress'])
	}
}
</script>

1-7步效果:

  1. 运行mongodb,再运行server端
  2. 运行client端
  3. 查看控制台网络请求、vue开发插件

在这里插入图片描述
在这里插入图片描述

6. getters.js 获取状态


三、vuex状态的使用

1.读取vuex的标题状态page/Msite.vue

此步要配合二.7步,先dispatch状态

====template内容:====
<!--3】读取vuex管理的状态:地址的name,别忘记加冒号动态绑定 -->
<TopHeader :title='address.name'>

===script内容:====
import {mapState} from 'vuex' //【1】调用vuex管理的状态
computed:{
    //【2】把vuex管理的地址状态对象复制到当前位置(来自store/state.js)
    ...mapState(['address'])
  }

效果:http://localhost:8080/#/msite

在这里插入图片描述

2.用vue的action-dispatch进行ajax请求获取滑动导航数据,并放在vuex中管理,取得categorys数组,转换成2维数组,最后显示在视图中

1)page/msite.vue script部分

data(){
    return{
    //【4】从文档中确定导航小图标,图片的基础地址
      baseImgUrl:'https://fuss10.elemecdn.com'
    }
  },
mounted(){
    // 【1】用vuex的action发起ajax请求,获取滑动导航分类放入vuex状态中
    //getCategorys来自actions.js
    this.$store.dispatch('getCategorys')
    ...其它代码略过
},
computed:{
    //【2】读取vuex管理的状态:地址/滑动导航分类解构到当前位置
    /*mapState返回的值:函数(对象)
      参数来自store/state.js*/
    ...mapState(['address','categorys'])
    
//【3】把categorys转化为二维数组x(滑动导航页数)*8(每页8个导航)
    categoryArr(){
      const max=8
      const {categorys}=this
      const arr=[]
      let minArr=[]
      categorys.forEach((c,index)=>{
        if(minArr.length===0){
          arr.push(minArr)
        }
        minArr.push(c)
        if(minArr.length===max){
         minArr=[]
        }
      })
      return arr
    }
},

至此应该能从vue调试工具中看到msite的相关数据
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

2) template部分:

可根据调试工具直接把导航改成v-for

<!--首页导航-->
        <nav class="msite_nav">
          <!--1】如果导航内有数据则显示导航部分 -->
          <div class="swiper-container" v-if='categorys.length'>
            <div class="swiper-wrapper">
              <!--3】循环2维数据categoryArr读取所有的值并写入其中 -->
              <div class="swiper-slide" v-for="(categorys,k) in categoryArr" :key='k'>
                <a href="javascript:" class="link_to_food" v-for="(category,k) in categorys" :key='k'>
                  <div class="food_container">
                    <img :src="baseImgUrl+category.image_url">
                  </div>
                  <span>{{category.title}}</span>
                </a>
              </div>

            </div>
            <!-- Add Pagination -->
            <div class="swiper-pagination"></div>
          </div>
          <!--2】如果导航内没有数据,则显示一张替代图片 -->
          <img src="./images/msite_back.svg" alt="back" v-else>
        </nav>
效果:

在这里插入图片描述

如果categorys为空是否显示else视图:用调试工具把categorys数组在vuex内清空,保存

在这里插入图片描述
显示:替换的图片,注意阴影圆和小广场即是替代没有数据时的图片

在这里插入图片描述

3.swiper无法滑动问题解决watch,vm.nextTick()使用

当做到第二步后查看页面,发现滑动导航无法翻页
原因是swiper加载的时机不对
解决:使用watch监视指定数据,且在此数据的视图更新后再运行即可,原mounted刻删除

msite.vue/script里

export default{
  watch:{//监视页面指定数据更新后执行
    categorys(value){//categorys数据更新后
      this.$nextTick(()=>{//categorys的数据的视图更新后再执行以下内容

        //创建一个Swiper对象,实现滑动轮播
        new Swiper('.swiper-container',{
          //配置参数
          direction: 'horizontal', //水平切换.垂直:vertical
          loop: true, // 循环滚动
          // 分页器
          pagination: {
            el: '.swiper-pagination',
            clickable:true,
          },     
        })

      })
    }
  }
  
}

至此即可正常切换

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值