Vue使用Vuex一步步封装并使用store

本文详细介绍Vue.js应用中Vuex仓库的搭建与使用,包括安装依赖、封装store、使用state、getters、mutations和actions等功能,以及如何通过modules进行模块化管理。

精简版

一、安装Vuex依赖

cnpm install vuex --save

二、一步步封装store

1. main.js中全局引入store仓库(下一步创建)

import store from './store' //引入store
 
new Vue({
  el: '#app',
  router,
  store, //挂载store,this将自动生成$store属性
  template: '<App/>',
  components: { App }
})

挂载store,this将自动生成$store属性

2. this.$store

创建store仓库:习惯在src下创建store文件夹,再创建index.js,内容:

import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex);
const store = new Vuex.Store();
 
export default store;

此时你已经有了一个空的store全局仓库,没有任何功能,但可以在任何vue实例下使用 this.$store 去访问它。

  • store使用范围均是可以全局使用;
  • let a=1; {a:a}.a 的缩写是 {a}.a,即当字典的键和值命名一样时,可以省略只写a
  • state、getters、mutations、mutations均是Vuex封装好的特殊变量,以下声明的功能变量均是这些名字,一个好处是store挂载该功能时可以简写(如3-1,本例均如此)。当然你也可直接在store中写功能(如3-2)。

3. this.$store.state

给store仓库读取数据功能:state

/*********  3-1 **********/
import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex);
 const state={ //要设置的全局访问的state对象,赋予初始属性值
     themeColor: {val:'blue',opacity:false},
     changeThemeCount:0,
     cache:''
   }; 
 const store = new Vuex.Store({
       state
    });
 
export default store;

此时你的store仓库已经有了存取数据的功能,可以用 this.$store.state.themeColor 等数据了。
下面是第二种写法

/*********  3-2 **********/
import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex);

const store = new Vuex.Store({
      state:{
       	 //要设置的全局访问的state对象,赋予初始属性值
	     themeColor: {val:'blue',opacity:false},
	     changeThemeCount:0,
	     cache:''
       }
    });
 
export default store;

4. this.$store.getters(this. $store.state的升级)

给state功能升级,让他拥有计算能力(类似vue中的computed方法):getters:

import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex);
 const state={ //要设置的全局访问的state对象,赋予初始属性值
     themeColor: {val:'blue',opacity:false},
     changeThemeCount:0,
     cache:''
   }; 
const getters = {   //实时监听state值的变化(最新状态)
    getThemeColor(state) {  //定义函数,返回处理过的val,命名最好有代表性
       let hour = new Date().getHours();
       // 如果白天则主题色不透明,反之
       state.themeColor.opacity = 8 <= hour && hour <= 20;
       return state.themeColor
    }
};
const store = new Vuex.Store({
       state, // 挂载存取数据功能
       getters //挂载数据计算功能
});
export default store;

此时使用 this.$store.getters.getThemeColor 获取颜色,将自动根据时间的不同自动设置主题是否有透明的效果

5. this.$store.commit(‘mutations’)

给store仓库使用函数功能(只为操作state数据):mutations - 同步

import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex);
 const state={ //要设置的全局访问的state对象,赋予初始属性值
     themeColor: {val:'blue',opacity:false},
     changeThemeCount:0,
     cache:''
   }; 
const getters = {   //实时监听state值的变化(最新状态)
    getThemeColor(state) {  //定义函数,返回处理过的val,命名最好有代表性
       let hour = new Date().getHours();
       // 如果白天则主题色不透明,反之
       state.themeColor.opacity = 8 <= hour && hour <= 20;
       return state.themeColor
    }
};
const mutations = {
    //自定义改变state初始值的方法,这里面的参数除了state之外还可以再传额外的参数(变量或对象);
    clearCatch(state) { 
        state.cache = "";
        state.changeThemeCount= 0;
    },
    setThemeColor(state,color,opacity){ 
       state.themeColor.val = color;
       state.themeColor.opacity = opacity;
       state.changeThemeCount++;
    }
};
const store = new Vuex.Store({
        state, // 挂载存取数据功能
       getters, //挂载数据计算功能
       mutations // 挂载函数功能
});
export default store;

此时可以使用 this.$store.commit(‘setThemeColor’,‘grey’,‘1’) 了(注意第一个参数是函数名,不是传参给state的,state自己会传,后两个才是对应传参)。可以主动设置主题色和透明度,操作是同步的,即如果你在同一个组件连续调用多次setThemeColor函数,获取仓库中state.changeThemeCount的值是一样的,下面介绍异步函数。

6. this.$store.dispatch(‘actions’)(this. $store.commit(‘mutations’)的升级)

给store仓库的函数commit功能升级(只为异步操作mutations中的函数):actions - 异步

import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex);
 const state={ //要设置的全局访问的state对象,赋予初始属性值
     themeColor: {val:'blue',opacity:false},
     changeThemeCount:0,
     cache:''
   }; 
const getters = {   //实时监听state值的变化(最新状态)
    getThemeColor(state) {  //定义函数,返回处理过的val,命名最好有代表性
       let hour = new Date().getHours();
       // 如果白天则主题色不透明,反之
       state.themeColor.opacity = 8 <= hour && hour <= 20;
       return state.themeColor
    }
};
const mutations = {
    //自定义改变state初始值的方法,这里面的参数除了state之外还可以再传额外的参数(变量或对象);
    clearCatch(state) { 
        state.cache = "";
        state.changeThemeCount= 0;
    },
    setThemeColor(state,color,opacity){ 
       state.themeColor.val = color;
       state.themeColor.opacity = opacity;
       state.changeThemeCount++;
    }
};
const actions = {
    //自定义触发mutations里函数的方法,context与store 实例具有相同方法和属性
    setThemeColorAction(context,color,opacity){
     	context.commit('setThemeColor',color,opacity);
    }
};
const store = new Vuex.Store({
       state, // 挂载存取数据功能
       getters, //挂载数据计算功能
       mutations, // 挂载函数功能
       actions, // 挂载异步函数
});
export default store;

此时可以使用 this.$store.dispatch(‘setThemeColorAction’,‘grey’,‘1’) 了(注意第一个参数是函数名,不是传参给context的,context自己会传,后两个才是对应传参)。可以主动设置主题色和透明度,操作是异步的,即如果你在同一个组件连续调用多次setThemeColorAction函数,获取仓库中state.changeThemeCount的值就不是一样的。

7.strict严格模式

export default new Vuex.Store({
  strict: true,
  state: {
    ...
  },
  ...
}

此模式下所有的状态变更(即更新state)必须使用mutation(commit),如果在组件中直接修改state则会报错。这样的好处是所有的state的更新都体现在仓库中,整改方便;使用devTools调试工具时可以跟踪到状态的修改。

三、modules 模块化

第二个模块介绍了store仓库的四个功能:state、getters、mutations和actions,下面介绍第五个功能:modules。

  • 当项目比较大时,一个store中数据会非常多而复杂,不易管理。此时便可建多个“子仓库”,分别对应不同模块做数据的读取和操作。
  • 注意主仓库还是那一个,只要把他的“子仓库”放在主仓库的modules下即可。
  • 子仓库看着很像仓库,其实它并不是store的实例,不是仓库(new Vuex.Store()实例化后的对象才是仓库),只是一个普通js对象(字典)。

1、在store下新建modules文件夹,在modules下新建home.js“子仓库”。
在这里插入图片描述
即home.js只管主页下的数据(一般不要分的太细,最多一个页面一个仓库管简洁),下面是home.js代码

//home.js

const state={
    users:[] //存访问该页面的所有用户
};
const getters={
  getUsers(state){ //获取访问该页面的所有用户
    // 对数据清理-除去脏数据
  	if (state.users.includes('*')) delete state.users['*'] 
    	return state.users;
  }
};
const mutations={
     addUser(state,name){ //增加访问用户
        state.collects.push(name)
     }
 };
const actions={
    invokeAddUser(context,name){ //触发mutations里面的addUser,传入数据形参name对应到users
        context.commit('addUser',name);
    }
};
// 注意和仓库的区别
const store = {
     // namespaced用于在全局引用此文件里的方法时标识这一个的文件名,使得让人明白这些数据来自哪个仓库
     // 即当你需要在别的文件里面使用子仓库(mapStates、mapGetters、mapActions)时,里面的方法需要注明来自哪一个模块的方法
     namespaced:true,
     state,
     getters,
     mutations,
     actions
}
export default store;

2.“子仓库”创建完成,要让主仓库引用它:

import Vue from 'vue';
import Vuex from 'vuex';
import home from './modules/home.js'

Vue.use(Vuex);
 const state={ //要设置的全局访问的state对象,赋予初始属性值
     themeColor: {val:'blue',opacity:false},
     changeThemeCount:0,
     cache:''
   }; 
const getters = {   //实时监听state值的变化(最新状态)
    getThemeColor(state) {  //定义函数,返回处理过的val,命名最好有代表性
       let hour = new Date().getHours();
       // 如果白天则主题色不透明,反之
       state.themeColor.opacity = 8 <= hour && hour <= 20;
       return state.themeColor
    }
};
const mutations = {
    //自定义改变state初始值的方法,这里面的参数除了state之外还可以再传额外的参数(变量或对象);
    clearCatch(state) { 
        state.cache = "";
        state.changeThemeCount= 0;
    },
    setThemeColor(state,color,opacity){ 
       state.themeColor.val = color;
       state.themeColor.opacity = opacity;
       state.changeThemeCount++;
    }
};
const actions = {
    //自定义触发mutations里函数的方法,context与store 实例具有相同方法和属性
    setThemeColorAction(context,color,opacity){
     	context.commit('setThemeColor',color,opacity);
    }
};
const store = new Vuex.Store({
       state, // 挂载存取数据功能
       getters, //挂载数据计算功能
       mutations, // 挂载函数功能
       actions, // 挂载异步函数
       modules:{ // 挂载子仓库
         home
    	}
});
export default store;

此时便有了第一个“子仓库”了!

四、使用仓库

1、无map系列

适合使用场景较少:
建好仓库,组件中直接使用state、getters、mutations、actions:

  • this.$store.state.*
  • this.$store.getters.*
  • this.$store.commit.*
  • this.$store.dispatch.*

2、map映射系列

适合使用场景频繁:
1、使用mapGetters、mapActions 和 mapStates之前需要import导入:

import {mapState,mapGetters,mapActions} from 'vuex';

2、使用ES6新语法-超引用,将某个功能下的数据或方法全部映射出来以供使用,下面是mapState、mapGetters、mapActions的例子:

	//这里的...是超引用,映射内容,可以写在computed下、methods下等(一般放在开头)
	// 直接从库中取值 - 将库里的users值返回给字典中的users并映射给this组件
 	...mapState({  
         users:state=>state.home.users  
      }),
     // 使用计算属性 - 将库里的users计算后的值返回给字典中的users并映射给this组件
    ...mapGetters('home',{ 
         users:'getUsers' //获取清理后的数据
         //由于home仓库 namespaced:true,所以第一个参数作为标识
         // 不使用标识访问的是主仓库
      })
      // 使用异步函数 - 以数组中的函数名,从库中对应的函数映射给this组件以供使用
    ...mapActions('home',['invokeAddUser'])
    // 有某个组件 <span @click='invokeAddUser(name)'></span>
    // 或者直接使用 this.invokeAddUser(name)

3、扩展

1、mapState映射的三种写法
  computed: mapState({
   // 箭头函数可使代码更简练
    count: state => state.count,

    // 传字符串参数 'count' 等同于 `state => state.count`
    countAlias: 'count',

    // 为了能够使用 `this` 获取局部状态,必须使用常规函数
    countPlusLocalState (state) {
      return state.count + this.localCount
    }
  })
  
2、当映射的计算属性的名称与state的子节点名称相同时,
   我们也可以给 mapState传一个字符串数组。
  computed: mapState([ // 数组
   "count"
  ])
  
3、仓库中action的第二种接收参数
const actions = {
    //自定义触发mutations里函数的方法,{commit}与store 实例具有相同方法和属性
    setThemeColorAction({commit},color,opacity){
     	commit('setThemeColor',color,opacity);
    }
};

3、总结

1、Vuex 是一个专门为 Vue.js 应用所设计的集中式状态管理架构。它借鉴了 Flux 和 Redux 的设计思想,但简化了概念,并且采用了一种为能更好发挥 Vue.js 数据响应机制而专门设计的实现。

2、Vuex 的四个核心概念分别是:
The state tree:Vuex 使用单一状态树,用一个对象就包含了全部的应用层级状态。至此它便作为一个『唯一数据源(SSOT)』而存在。这也意味着,每个应用将仅仅包含一个 store 实例。单状态树让我们能够直接地定位任一特定的状态片段,在调试的过程中也能轻易地取得整个当前应用状态的快照。
Getters: 用来从 store 获取 Vue 组件数据。
Mutators: 事件处理器用来驱动状态的变化。
Actions: 可以给组件使用的函数,以此用来驱动事件处理器 mutations

3、Vuex 应用中数据的流向(Vuex 官方图)
在这里插入图片描述

  • 数据流都是单向的
  • 组件能够调用 action
  • action 用来派发 Mutation
  • 只有 mutation 可以改变状态
  • store 是响应式的,无论 state 什么时候更新,组件都将同步更新

参考文献:
思否-飞跃
思否-离尘不理人

<think>嗯,用户想用Vue做前端,PHP做后端来开发一个网络商城项目。我需要先理清楚整个项目的结构和步骤,确保用户能明白如何开始和进行下去。 首先,用户可能对前后端分离的架构不太熟悉,需要解释清楚前后端各自的职责。比如前端负责页面展示和交互,后端处理数据和业务逻辑,通过API通信。这样分开的好处是前后端可以独立开发,提高效率。 接下来要考虑技术选型。Vue方面,用户可能需要使用Vue 3,因为现在是主流,还有Vue Router和Vuex或者Pinia来管理状态。UI框架的话,Element Plus或者Ant Design Vue都是不错的选择,能加快开发。PHP后端的话,Laravel是个好框架,因为它功能强大,社区支持好,而且自带很多工具,比如ORM、路由和身份验证。数据库的话MySQL比较常见,适合商城项目。API文档工具可以用Swagger,方便前后端协作。 然后是项目结构规划。前端部分可能需要用Vue CLI或者Vite创建项目,组织好组件、路由、状态管理和API请求模块。后端的话,Laravel的MVC结构,需要设计好路由、控制器、模型和数据库迁移。同时要规划RESTful API的接口,比如商品、用户、订单、购物车等模块的接口设计。 数据库设计是关键部分。用户可能需要设计商品表、用户表、订单表、订单项表、购物车表、分类表等。要考虑到字段的类型、索引和关联关系,比如商品和分类的多对多,订单和用户的一对多等。这部分需要详细说明,帮助用户避免常见的数据库设计错误。 开发步骤方面,应该分阶段进行。比如先搭建前后端的基础框架,然后实现用户认证,接着是商品模块,购物车和订单流程,最后是支付集成。每个步骤需要给出具体的实现方法,比如用JWT做用户认证,Laravel Sanctum来处理API令牌,Vue使用axios拦截器处理token等。 接口联调测试阶段,要推荐工具如Postman或Swagger,方便前后端协作测试接口。同时要处理跨域问题,比如在Laravel中配置CORS中间件,或者前端代理设置。 部署阶段需要分开部署前后端。前端可以用Nginx或托管服务,后端则需要配置服务器环境,比如Laravel的环境要求,使用Envoyer或Forge简化部署。数据库迁移和填充数据也是需要注意的地方。 进阶优化部分,比如缓存、队列、性能优化和SEO,这些可能在项目后期需要考虑。用户可能对SEO有需求,所以需要提到SSR或Nuxt.js的方案。 最后,推荐一些学习资源,帮助用户深入理解各个技术点,比如Vue和Laravel的官方文档,以及RESTful API设计的最佳实践。 整个过程中,需要确保用户能够按照步骤一步步搭建项目,同时了解每个环节的作用和实现方法。可能还需要提醒用户注意安全性,比如SQL注入、XSS攻击的防范,以及在支付集成时的合规性问题。</think>好的!使用 Vue 作为前端、PHP 作为后端开发网络商城的整体思路可以分为**前后端分离架构**,前端通过 API 与后端通信。以下是详细步骤和关键技术点: --- ### **一、技术选型建议** #### **前端 (Vue.js)** - **Vue 3**:主流版本,支持组合式 API - **Vue Router**:管理页面路由 - **Vuex/Pinia**:状态管理(推荐 Pinia) - **UI 框架**:Element Plus / Ant Design Vue / Vuetify(快速搭建界面) - **Axios**:HTTP 请求库,与后端 API 交互 - **Vite**:构建工具(替代 Webpack,速度更快) #### **后端 (PHP)** - **Laravel/Lumen**:推荐框架(内置 RESTful API 支持、ORM、路由等) - **MySQL**:主流关系型数据库 - **JWT/Passport**:用户认证方案(推荐 Laravel Sanctum) - **Swagger**:API 文档生成工具 - **Redis**:缓存、购物车临时存储 --- ### **二、项目结构规划** #### **前端项目结构** ```bash src/ ├── api/ # 后端接口请求封装 ├── assets/ # 静态资源 ├── components/ # 公共组件 ├── router/ # 路由配置 ├── store/ # 状态管理(Pinia) ├── views/ # 页面组件 └── main.js # 入口文件 ``` #### **后端项目结构(Laravel 示例)** ```bash app/ ├── Http/ │ ├── Controllers/ # 控制器(如ProductController) │ └── Middleware/ # 中间件(如验证Token) routes/ ├── api.php # API 路由定义 database/ ├── migrations/ # 数据库迁移文件 ├── seeders/ # 测试数据填充 ``` --- ### **三、核心功能模块** 1. **用户模块**:注册/登录、权限管理(JWT Token) 2. **商品模块**:分类管理、商品列表/详情、搜索筛选 3. **购物车模块**:添加/删除商品、实时计算总价 4. **订单模块**:生成订单、支付回调(可集成支付宝/微信) 5. **后台管理**:商品/订单管理(需单独权限控制) --- ### **四、数据库设计(关键表)** ```sql -- 商品表 CREATE TABLE products ( id INT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(255), price DECIMAL(10,2), description TEXT, category_id INT, stock INT ); -- 订单表 CREATE TABLE orders ( id INT PRIMARY KEY AUTO_INCREMENT, user_id INT, total_amount DECIMAL(10,2), status ENUM('pending', 'paid', 'shipped') ); -- 购物车表(可存Redis) CREATE TABLE carts ( user_id INT, product_id INT, quantity INT ); ``` --- ### **五、开发步骤** #### **1. 搭建基础框架** - 前端:`npm create vue@latest` 初始化 Vue 项目 - 后端:`composer create-project laravel/laravel` 初始化 Laravel #### **2. 用户认证** - 后端:使用 Laravel Sanctum 生成 API Token - 前端:Axios 请求时携带 `Authorization: Bearer {token}` #### **3. 商品模块接口示例(Laravel)** ```php // routes/api.php Route::group(['middleware' => 'auth:sanctum'], function() { Route::apiResource('products', ProductController::class); }); // app/Http/Controllers/ProductController.php public function index() { return Product::paginate(10); // 分页返回商品 } ``` #### **4. 前端调用示例(Vue)** ```javascript // api/product.js import axios from 'axios'; export const getProducts = (params) => { return axios.get('/api/products', { params }); } // Vue 组件中 import { getProducts } from '@/api/product'; const loadData = async () => { const res = await getProducts({ page: 1 }); productList.value = res.data.data; } ``` --- ### **六、关键问题处理** 1. **跨域问题**:在 Laravel 中配置 `config/cors.php` 2. **图片上传**:前端通过 FormData 发送,后端保存到 `storage/app/public` 3. **支付集成**:使用支付宝/微信的 SDK,处理异步回调 4. **性能优化**:Redis 缓存热门商品、Vue 组件懒加载 --- ### **七、部署方案** - **前端**:`npm run build` 生成静态文件,部署到 Nginx 或 CDN - **后端**:使用 Laravel Forge / Envoyer,配置 PHP 环境和队列任务 - **数据库**:云服务(如 AWS RDS/AliCloud)或自建 MySQL --- ### **八、学习资源推荐** - Vue 官方文档:https://vuejs.org/ - Laravel 中文文档:https://learnku.com/docs/laravel - RESTful API 设计指南:https://restfulapi.net/ 需要更详细的某个环节(如支付集成、权限设计)可以告诉我,我可以提供具体代码示例! 😊
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值