前言:Vuex是一个专门为Vue.js应用程序开发的状态管理模式, 它采用集中式存储管理所有组件的公共状态, 并以相应的规则保证状态以一种可预测的方式发生变化.

Vuex的四大核心

1.state 驱动应用的数据源
2.mutations 基因突变 类如C# 属性get set
3.actions 行为
4.getters 读取器

上图中绿色虚线包裹起来的部分就是Vuex的核心, state中保存的就是公共状态, 改变state的唯一方式就是通过mutations进行更改. 可能你现在看这张图有点不明白, 等经过本文的解释和案例演示, 再回来看这张图, 相信你会有更好的理解.

如何引入Vuex?

1.npm install vuex

2.装好了之后,在全局上去使用你的Vuex

3.创建Store对象,最好在src创建一个store这样的文件夹然后创建index.js

4.在main.js中注册使用

import Vuex from 'vuex'

Vue.use( Vuex );

const store = new Vuex.Store({
//待添加
}) new Vue({
el: '#app',
store,
render: h => h(App)
})

  

为了讲解Vuex,我们做了一个项目,这个项目需要连接apicloud,异步操作使用了axios以及样式bootstrap,其中包括了登录注册以及其中的父组件向子节点传值等,我们给项目安装相关的modules

npm install bootstrap
npm install axios

router.js

import Vue from 'vue'
import Router from 'vue-router' Vue.use(Router) export default new Router({
routes: [
{
path: '/',
name: 'index',
component:()=>import('../views/index.vue')
},
{
path:'/detail/:id',
name:'detail',
component:()=>import ('../views/detail.vue')
},
{
path:'/login',
name:'login',
component:()=>import ('../views/login.vue')
},
{
path:'/register',
name:'register',
component:()=>import ('../views/register.vue')
}
]
})

store.js

 

我们来上述代码中来讲解其中vuex的奥秘,State就是所有组件提出来的data,用于所有组件公共数据,而其中mutations就像C#中get\set,属性赋值器,其中方法的两个参数除了state只能带一个参数。

actions是操作数据的方法,说过说你的actions中需要改变state中的数据,那么必须要通过commit关键字去提交给mutations,还有一点就是actions中很多操作都是关于异步处理的,最关键就是它是操作state数据的,那getters是什么呢?它是组件访问vuex的入口,里面写好了方法去操作,它也是过滤器,就像程序中的三层架构BLL.

main.js

// The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
import Vue from 'vue'
import App from './App'
import router from './router'
import boostrap from 'bootstrap/dist/css/bootstrap.css'
import store from './store/index.js' Vue.config.productionTip = false /* eslint-disable no-new */
new Vue({
el: '#app',
router,
store,//在全局对象上加载仓库
components: { App },
template: '<App/>'
}) 

两个组件

import Vue from 'vue'
import Vuex from 'vuex'
import API from '../utils/api.js' var api = new API('goods')
var userApi = new API('userinfo'); Vue.use(Vuex); const state = {
user: null,
products: []
}
const mutations = {
//加载产品数据
INIT_PRODUCTS(state, data) {
state.products = data;
},
SET_LOGIN_USER(state, u) {
state.user = u;
}
}
const actions = {
LOAD_PRODUCTS({ commit }) {
api.Select().then(res => {
commit('INIT_PRODUCTS', res.data);
})
},
LOGIN({ commit }, user) {
return userApi.Select().then(res => {
let users = res.data;//所有的用户
for (let u of users) {
if (u.name == user.name && u.password == user.password) {
commit('SET_LOGIN_USER', u);
return u;
}
}
})
},
REGISTER({ commit }, user) {
return userApi.Insert(user).then(res => {
console.log(res.data);
return 'OK';
}).catch(err => {
return err;
})
} }
const getters = {
ALL_PRODUCTS(state) {
return state.products;
},
GET_PRODUCT_BYID: (state) => function (id) {
//遍历 is == id
for (let p of state.products) {
if (p.id == id) {
return p;
}
}
return null;
}
} //仓库
const store = new Vuex.Store({
state: state,
mutations: mutations,
actions: actions,
getters: getters
})
export default store;

  

navbar.vue

<template>
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
<div class="container">
<a class="navbar-brand" href="#">购物车</a>
<ul class="navbar-nav ml-auto">
<li class="nav-item active dropdown" v-if="user!==null">
<a class="nav-link dropdown-toggle" data-toggle="dropdown" @click="showDropdown=!showDropdown">欢迎你:{{user.name}} </a>
<div class="dropdown-menu show">
<a class="dropdown-item" href="#">我的订单</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item" >注销</a>
</div>
</li>
<li class="nav-item active" style="margin-right:5px" v-if="user===null">
<router-link class="nav-link btn btn-warning btn-sm" style="color:#fff" to="/login">登录</router-link>
</li>
<li class="nav-item active" v-if="user===null">
<router-link class="nav-link btn btn-danger btn-sm" style="color:#fff" to="/register">注册</router-link>
</li>
</ul>
</div>
</nav>
</template> <script>
export default {
data(){
return{
showDropdown:false
}
},
computed:{
user(){
return this.$store.state.user;
} }
}
</script>

  

product.vue 该组件用于显示商品的详细信息

<template>
<div class="card">
<img class="card-img-top" src="../../assets/logo.png" alt="Card image cap">
<div class="card-body">
<h5 class="card-title">{{product.name}}</h5>
<p class="card-text">{{product.description===null?"暂无描述":product.description}}</p>
<p>价格: {{product.price}}</p>
<a href="#" class="btn btn-warning float-left" @click="goDetail">查看详情</a>
<a href="#" class="btn btn-primary float-right">加入购物车</a>
</div>
</div>
</template> <script>
export default {
props:['product'],
methods:{
goDetail(){
console.log(this.product.id);
this.$router.push(`/detail/${this.product.id}`);
}
}
}
</script>

  

程序入口APP.vue

<template>
<div id="app">
<nav-bar></nav-bar>
<router-view></router-view>
</div>
</template> <script>
import NavBar from './views/components/navbar'
export default {
name: 'App',
components:{NavBar}
}
</script>

注册:通过this.$store.dispatch去调用actions中的方法,其中有趣的是commit的参数竟然被方法名给..这个以后在思考。。

<template>
<div class="container">
<div class="row">
<div class="card" style="margin:50px auto;width:400px">
<div class="card-body">
<h5 class="card-title">注册</h5>
<hr>
<div class="form-group">
<label for="">用户名</label>
<input type="text" class="form-control" v-model="user.name">
</div>
<div class="form-group">
<label for="">真实姓名</label>
<input type="text" class="form-control" v-model="user.realname">
</div>
<div class="form-group">
<label for="">密码</label>
<input type="password" class="form-control" v-model="user.password">
</div>
<div class="form-group">
<button class="btn btn-primary btn-block" @click="register">注册</button>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
data(){
return{
user:{
name:'',
realname:'',
password:''
}
}
},methods:{
register(){
this.$store.dispatch('REGISTER',this.user).then(res=>{
if(res=="OK")
this.$router.push('/index');
})
}
}
}
</script> 

  

 登录

<template>
<div class="container">
<div class="row">
<div class="card" style="margin:50px auto;width:400px">
<div class="card-body">
<h5 class="card-title">登录</h5>
<hr>
<div class="form-group">
<label for="">用户名</label>
<input type="text" class="form-control" v-model="user.name">
</div>
<div class="form-group">
<label for="">密码</label>
<input type="password" class="form-control" v-model="user.password">
</div>
<div class="form-group">
<button class="btn btn-primary btn-block" @click="login">登录</button>
</div>
</div>
</div>
</div>
</div>
</template> <script>
export default {
data(){
return {
user:{
name:'',
password:''
}
}
},
methods:{
login(){
this.$store.dispatch('LOGIN',this.user).then(res=>{
console.log(res);
if (res){
this.$router.push('/')
}
})
}
}
}
</script>
 主页面 <template>
<div class="container">
<h1>商品列表</h1>
<div class="row">
<div class="col-md-4" v-for="p in products" :key="p.id">
<!-- 传递商品信息到子组件 -->
<product-card :product="p"></product-card>
</div>
</div>
</div>
</template> <script>
import ProductCard from './components/product.vue'
export default {
components:{ProductCard},
computed:{
products(){
return this.$store.getters.ALL_PRODUCTS;
}
},
created(){
this.$store.dispatch('LOAD_PRODUCTS');
}
}
</script>

  

本文结语知识总结:

获取url中的参数

let id = this.$route.params.id;
this.details = this.$store.getters.GET_PRODUCT_BYID(id);

有的小伙伴在复制我的代码运行报错,说什么未初始化;一定要在index.vue添加这个代码,LOAD_PRODUCTS给数据初始化

    created(){
this.$store.dispatch('LOAD_PRODUCTS');
}

跳转路由

this.$router.push('/')

ApiClound万能帮助类

import crypto from 'crypto'     // 加密
import axios from 'axios'
class API {
constructor(classname){
this.api = `https://d.apicloud.com/mcm/api/${classname}`;
let ID = '';
let KEY = '';
let now = Date.now(); //当前时间
let sha1 = crypto.createHash('sha1');
sha1.update(ID + "UZ" + KEY + "UZ" + now);
axios.defaults.headers["X-APICloud-AppId"] = ID;
axios.defaults.headers["X-APICloud-AppKey"] = sha1.digest('hex') + "." + now;
} Select(){
return axios.get(this.api);
}
Insert(obj){
return axios.post(this.api,obj);
}
Update(id,obj){
// RESTFUL API
return axios.put(this.api+`/${id}`,obj);
}
Delete(id){
return axios.delete(this.api + `/${id}`);
}
} export default API;

  

 还有同学问我父组件和子组件如何传值?

在父页面引用的地方以":"表示的值都可以在子页面的props获取到

<template>
<div>
<h3>图书管理</h3><hr>
<div class="row">
<div class="col-md-4 col-sm-4" v-for="b in books" :key="b.id">
<book-detail @abc="xyz" :Book="b" :MSG="abc"></book-detail>
</div>
</div>
</div>
</template>
<script>
import BookDetail from './components/BookDetails.vue'
export default{
components:{BookDetail},
data(){
return {
abc:'heheda',
books:[{
id:1,
name:'7天 JAVA 从入门到放弃',
text:'到底是人性的扭曲,还是道德的沦丧. 青年男子为何突然脱发,中年男人为何删库跑路。',
price:20,
img:'img2.jpg',
showHehe:true
},{
id:2,
name:'7天 C# 从入门到自杀',
text:'到底是人性的扭曲啊,还是道德的沦丧啊. 祖国的花朵为何自杀。',
price:20,
img:'../../static/img2.jpg',
showHehe:false
}]
}
},
methods:{
xyz(bid){
alert(bid);
}
}
}
</script>

  

在子页面中可以这么搞

<script>
export default{
props:["Book","MSG"],
created(){
console.log(this.Book.name);
},
methods:{
select(id){
this.$emit('abc',id);
},
detail(bid){
this.$router.push(`/admin/Details/${bid}`);
}
}
}
</script>

 而其中的$emit是可以调用父页面的方法的。

谢谢大家收看!!!

Vuex的基本概念、项目搭建、入坑点的更多相关文章

  1. IDEA下Maven项目搭建踩坑记----2.项目编译之后 在service层运行时找不到 com.dao.CarDao

    项目写的差不多 想运行一下,然后发现运行到Service层的时候报错说找不到Dao层文件 ,纠结半天之后看了下编译好的项目文件,发现mapper文件下边是空的, 于是就百度找一下原因,结果说是IDEA ...

  2. IDEA下Maven项目搭建踩坑记----1.pom,xml文件下${spring-version}不能用

    因为pom.xml文件是直接复制别人配好的web环境,所以在粘贴进去的之后有一部分没有粘贴到,因此出现爆红 解决方法:↓↓↓↓ 代码: <project.build.sourceEncoding ...

  3. IDEA下Maven项目搭建踩坑记----3.最长的bug,最简单的错误。同一类中,部分函数的@AutoWired注入的对象失效

    这个错误绝对是我写到现在为止最傻X的一个错误,先上图 问题: 出了一个特别长的错误,大致的意思就是mapper.xml文件注入Dao层的时候失败. 解决: 查看一下错误的位置→ 找到Dao层 找到错误 ...

  4. 入坑cordova

    原文:入坑cordova 因项目需要入坑cordova,奔跑吧骚年,目前只是要求安卓平台,下面都是以安卓为例 最好的学习资料还是官网. https://cordova.apache.org/ http ...

  5. SpringBoot入坑-项目搭建

    对于学过三大框架的小童鞋,从今天开始给大家带来一套新的框架学习,相信对于做程序的小童鞋一定有所耳闻,作为下一代java开发框架springboot,减去了繁琐的xml配置,相信用过spring.sta ...

  6. 《Asp.Net Core3 + Vue3入坑教程》-Net Core项目搭建与Swagger配置步骤

    简介 <Asp.Net Core3 + Vue3入坑教程> 此教程仅适合新手入门或者前后端分离尝试者.可以根据图文一步一步进操作编码也可以选择直接查看源码.每一篇文章都有对应的源码 教程后 ...

  7. Vue入坑教程(二)——项目结构详情介绍

    之前已经介绍了关于Vue的脚手架vue-cli的安装,以及一些文件目录介绍.具体可以查看<vue 入坑教程(一)--搭建vue-cli脚手架> 下面简单说一下具体的文件介绍 (一) pac ...

  8. 《Asp.Net Core3 + Vue3入坑教程》 - Vue 1.使用vue-cli创建vue项目

    简介 <Asp.Net Core3 + Vue3入坑教程> 此教程适合新手入门或者前后端分离尝试者.可以根据图文一步一步进操作编码也可以选择直接查看源码.每一篇文章都有对应的源码 目录 & ...

  9. 初入angular4——实际项目搭建总结

    前言 接到一个pc端后台项目,还会加入两个安卓同事一起学习和做这个项目,需要带一下他们. 既ng1之后,我就没怎么有过其它后台框架的实际项目经验了,期间用的移动端框架也并非vue.angular系列. ...

  10. 1、 小白带你入坑xamarin系列之环境搭建和准备

    重点提示 由于xamarin发展更新很快 目前教程部分内容已经过时 请注意下载最新版本   2018.05.23 www.xamarin.com 1. 小白带你入坑xamarin系列之环境搭建和准备 ...

随机推荐

  1. Python学习(四十二)—— Djago-model进阶

    一.QuerySet 可切片 使用Python 的切片语法来限制查询集记录的数目 .它等同于SQL 的LIMIT 和OFFSET 子句. Entry.objects.all()[:5] # (LIMI ...

  2. 【HTTP】---HTTP状态码详解

    https://en.wikipedia.org/wiki/List_of_HTTP_status_codes 1.百科名片 HTTP状态码(HTTP Status Code)是用以表示网页服务器HT ...

  3. vue基础4-数据绑定

    1.v-bind 只能实现数据额单向绑定,从M到V,无法实现数据的双向绑定 改变页面输入框的值,打印数据并未改变. 2.v-model 可以实现数据的双向绑定,从M到V.V到M.  注意:v-mode ...

  4. VSTO 获取sheet单元格行列数

    Public Sub Igor() Dim Dtsheet As Excel.Worksheet Dim TotalC As Long '原始数据范围列 Dim TotalR As Long '原始数 ...

  5. git 修改用户名和密码

    初次运行 Git 前的配置 一般在新的系统上,我们都需要先配置下自己的 Git 工作环境.配置工作只需一次,以后升级时还会沿用现在的配置.当然,如果需要,你随时可以用相同的命令修改已有的配置. Git ...

  6. 展开被 SpringBoot 玩的日子 《 四 》 Session 会话共享

    共享Session-spring-session-data-redis 分布式系统中,sessiong共享有很多的解决方案,其中托管到缓存中应该是最常用的方案之一. Spring Session官方说 ...

  7. if(){}使用

    1.当作 if else时使用 是判断if()括号内的内容和给定内容是不是相同 package cn.lyun.thread; class Demo{ boolean flag = false; pu ...

  8. 百度TTS的来由

    #### https://home-assistant.io/components/tts.baidu/#### https://github.com/charleyzhu/HomeAssistant ...

  9. VB中StdPicture尺寸(Width,Height)转像素单位

    首先获得一个图片对象 Dim spic As StdPicture Set spic = LoadPicture("d:\0.bmp") '从文件获得 Set spic = Cli ...

  10. 3.SSM整合_多表_一对多的增删改查

    1.配置文件跟上一章一样,这里就不多写了,主要是Mapper映射文件,一对多反过来就是多对一 一 接口 public interface CategoryMapper { public void ad ...