单词:
dispatch 派遣
-
Vuex 的状态存储是响应式的。当 Vue 组件从 store 中读取状态的时候,若 store 中的状态发生变化,那么相应的组件也会相应地得到高效更新。
-
你不能直接改变 store 中的状态。改变 store 中的状态的唯一途径就是显式地提交 (commit) mutation。这样使得我们可以方便地跟踪每一个状态的变化,从而让我们能够实现一些工具帮助我们更好地了解我们的应用。
实践:先做一个点击加减的计数器
<template>
<div>
<h2>首页</h2>
<div class="box">
<h1>number:{{count}}</h1>
<button @click="increase">+</button>
<button @click="decrease">-</button>
</div>
</div>
</template>
<script>
export default {
data() {
return {
count: 0
};
},
methods: {
increase() {
this.count++;
},
decrease() {
this.count--;
}
}
};
</script>
<style scoped>
.box {
height: 500px;
width: 500px;
background-color: #ccc;
margin: 0 auto;
}
</style>
vuex 实现:
注意 this.$store 一般使用在 script 比如数据呈现this不用加{{$store.count}}就行
去main.js
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import Vuex from 'vuex'
Vue.use(Vuex)
//注意 加上Store
var store = new Vuex.Store({
state:{
count:1
}
})
Vue.config.productionTip = false
new Vue({
router,
store,
render: h => h(App)
}).$mount('#app')
<h2>仓库中的count:{{$store.state.count}}</h2>
<button @click="addNum">+</button>
<button @click="subNum">-</button>
watcher“function(){return this.?state}”回调时出错:“错误:[vuex]不要在变异处理程序之外更改vuex存储状态。”
另外一种导入:
安装:npm install vuex --save
scr/store/index.js
import Vuex from 'vuex'
import Vue from 'vue'
// 1.安装
Vue.use(Vuex)
//2.创建对象
const store = new Vuex.Store({
state:{
count:1000
},
mutations:{
//方法:
addEvent(state){//state 就是上面的state对象 默认会传过来
// this.state.count++
state.count++
},
subEvent(state){
// this.state.count--
//不用加this了
state.count--
}
},
actions:{
},
getters:{
},
modules:{
}
})
//导出
export default store
// export default Store 注意这个s的大写有点难看清除
然后在main.js中导入
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
Vue.config.productionTip = false
new Vue({
router,
store,
render: h => h(App)
}).$mount('#app')
vuex.vue组件
<template>
<div>
<h2>vuex</h2>
<hr>
<h2>计算器:{{$store.state.count}}</h2>
<button @click = "add">+</button>
<button @click = "sub">-</button>
</div>
</template>
<script>
export default{
data() {
return {
}
},
methods: {
add(){
//提交 东西给store仓库
this.$store.commit('addEvent')
// console.log(111)
// console.log( this.$store.state.count)
},
sub(){
this.$store.commit('subEvent')
// console.log(222)
}
},
}
</script>
<style>
</style>
单一状态树
getters =>相当于我们的计算属性
什么时候使用计算属性?
比如说一个data中的变量需要经过一些列的操作才展示在页面上
让count平方在呈现在页面上
filter函数的使用
filter()接收的回调函数,其实可以有多个参数。通常仅使用第一个参数,表示Array的某个元素。回调函数还可以接收另外两个参数,表示元素的位置和数组本身:
利用filter,可以巧妙地去除Array的重复元素:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
// var arr = [0, 1, 2, 3, 4, 5, 1, 4, 0];
// var arr_filter = arr.filter(function (x) {
// return x % 2 == 0;/* 筛选偶数 */
// })
// console.log(arr_filter)
// var arr = ['0', 1, 2, 3, 4, "", 5, 1, 4, '0', ""];
// var arr_filter = arr.filter(function (x) {
// return x;/* 筛选空格 */
// })
// console.log(arr_filter)
// var arr = [1, '', null, undefined, ' ']
// console.log(arr.filter(v => v))
// var arr = ['A','B','C','d'];
// var arr_filter = arr.filter(function(element,index,self){
// console.log(element);/* 依次打印'A','B','C','d' */
// console.log(index);/* 依次打印0,1,2,3 */
// console.log(self);/* 打印数组本身即arr */
// return true;
// })
var arr_repeat = ['A','B','A','B','B','C','A','D'];
var arr_filter = arr_repeat.filter(function(element,index,self){
return self.indexOf(element) == index;
})
console.log(arr_filter);//返回['A','B','C','D']
</script>
</body>
</html>
现在在state中定义了数组对象:
现在有个需求: 大于年龄20 岁的 20不能写死 是动态传过来的
mutation
<button @click = "addFive">+5</button>
<button @click = "addTen">+10</button>
那能不能通过 一个发放代替 这两个两个方法呢? 可以的
<button @click = "addNum(5)">+5</button>
<button @click = "addNum(10)">+10</button>
addNum(num){
this.$store.commit('addNum',num)
}
mutations:{
addNum(state,num){
state.count += num
}
},
传入的参数 只有一个 我要传对象呢?
<h2>{{$store.state.students}}</h2>
<button @click="addStudents">添加学生</button>
addStudents(){
let stu = {name :"chenbo",id:52}
this.$store.commit('addStu',stu)
}
// mutation:
addStu(state,payload){
state.students.push(payload)
}
两种提交风格
一.普通的提交: this.$store.commit('addNum',num) 二.特殊的提交风格:
所以第二个参数 payload 是一个对象了
mutation 的响应规则
方法参数提示怎么实现?
导入方式:
//对象中的方法可以这样写
['fangfa'](){
xxx
}
mutation的异步操作
action
上面也是错误的 为啥 跳过了commit这一步
需求 :携带参数 并且执行完成后返回值给到前台
success为回调函数 什么是回调函数? 就是一个方法执行完要调用的函数 现在函数作为参数传值 把这个函数传递过去 它会在某一时刻(触发)被执行就会它里面的要呈现的信息返回
携带的参数 和回调的函数写在了一坨
不雅观
现在通过new promise()的方式 还可以从后台携带参数传递给前台 而且返回前台需要的信息 只需要传递携带信息就行
问题: vue中打印this 输出一个VueComponent 我怎么知道它是哪一个
module
ps:
但是在子模块中注意的是 在他里面做的异步操作 context.commit也只提交到自己模块中的actions中
- 子模块的context:
- 跟模块中的context:
项目结构
没有抽离的代码:
//store/index.js
import Vuex from 'vuex'
import Vue from 'vue'
import { ADDTOWNUM, YIBU } from './mutation_type.js'
// 1.安装
Vue.use(Vuex)
//3.创建module对象
const moduleA ={
state:{
name:'lumigqing'
},
mutations:{
upMyName(state,payload){
state.name = payload
}
},
actions:{
// asyncName(context,payload){
asyncName(context){//这里的context 可以用对象的结构写法
console.log(context)
setTimeout(()=>{
// 这里的context 自会调用自己模块的mutation
//提交 mutation本来就有的方法
// context.commit('upMyName',payload)//payload = 大番薯
context.commit('upMyName','dafanshu')//
},1000)
}
},
getters:{
fullName(state){
return state.name + '11111111'
},
fullName2(state,getters){
return getters.fullName + '22222'
},
//第三个参数 为根state
fullName3(state,getters,rootState){
return getters.fullName2 + '根'+rootState.count
}
},
modules:{
}
}
const moduleB ={
state:{
},
mutations:{
},
actions:{
},
getters:{
},
modules:{
}
}
const moduleC ={
state:{
},
mutations:{
},
actions:{
},
getters:{
},
modules:{
}
}
//2.创建对象
const store = new Vuex.Store({
state: {
//用于异步操作
actionData: 25,
count: 1000,
students: [
{ name: 'lulu', id: 12 },
{ name: 'lulu', id: 120 },
{ name: 'yige', id: 35 }
],
},
mutations: {
//方法:
addEvent(state) {//state 就是上面的state对象 默认会传过来
// this.state.count++
state.count++
},
subEvent(state) {
// this.state.count--
//不用加this了
state.count--
},
// addNum(state,num){
// console.log(num);
// state.count += num
// },
addNum(state, payload) {
console.log(payload.num);//10
console.log(payload.age);//30
state.count += payload.num
},
//添加一个对象 在student中
//注意是 在mutation这里的第二个参数 才叫做负载 payload
addStu(state, payload) {
state.students.push(payload)
},
updataName(state) {
state.students[2].name = "love"
},
addUserName(state) {
// state.students[2]['address'] = "天河区"
// set(参数1 obj/arr 2 key :string|number,value:)
Vue.set(state.students[2], 'address', '天河区')
},
deleteUser(state) {
// delete state.students[2].name
//为啥可以这样用?
Vue.delete(state.students[2], 'name')
},
// //对象中的方法可以这样写
// ['fangfa'](){
// xxx
// }
[ADDTOWNUM](state) {
state.count += 2
},
[YIBU](state) {
//不能在这里进行异步操作
setTimeout(() => {
state.students[2].id = "123"
}, 2000)
},
// 异步用的方法:
yibuFun(state) {
state.actionData = '福利来咯'
}
},
actions: {
// context上下文 暂时理解为store
// actionDataFun(context){
// setTimeout(()=>{
// context.commit('yibuFun')
// },2000)
// }
// actionDataFun(context,payload){//携带参数
// setTimeout(()=>{
// context.commit('yibuFun'),
// console.log(payload.message),//
// payload.success()//
// },2000)
// }
actionDataFun(context, payload) {//携带参数
console.log(context)
return new Promise((resolve, reject) => {
setTimeout(() => {
context.commit('yibuFun'),
// console.log(payload), 结束不能加逗号
console.log(payload)//我是携带的信息
// resolve() 里面可以携带参数
resolve('这是resolve的传递参数')
}, 2000)
})
}
// actionDataFun(context){
// setTimeout(()=>{
// // 错误写法
// context.state.actionData = '日了狗了'
//
// },2000)
// }
},
getters: {
},
modules: {
//把state 划分成不同的模块
a:moduleA,
b:moduleB,
c:moduleC,
}
})
//导出
export default store
// export default Store 注意这个s的大写有点难看清除
组件Vuex:
<template>
<div>
<h2>vuex</h2>
<hr>
<h2>计算器:{{$store.state.count}}</h2>
<button @click="add">+</button>
<button @click="sub">-</button>
<!-- <button @click = "addFive">+5</button>
<button @click = "addTen">+10</button> -->
<button @click="addNum(5)">+5</button>
<button @click="addNum(10)">+10</button>
<hr>
<hr>
<h2>{{$store.state.students}}</h2>
<button @click="addStudents">添加学生</button>
<hr>
<hr>
<h2>{{$store.state.students[2]}}</h2>
<p>点击按钮把‘yige’修改成love</p>
<button @click="updateName">修改用户信息</button>
<button @click="addName">添加用户信息</button>
<button @click="deleteUser">删除用户信息</button>
<hr>
<hr>
<h2>常量方法加2 :{{$store.state.count}}</h2>
<button @click="addTow">+2</button>
<hr>
<hr>
<h3>mutation的异步操作 是跟踪不到的</h3>
<h2>{{$store.state.students[2]}}</h2>
<button @click="editId">修改用户id</button>
<hr>
<hr>
<h3>action 模拟异步操作</h3>
<h3>action:{{$store.state.actionData}}</h3>
<button @click=" handlerActionData">修改数字</button>
<hr>
<hr>
<h2>modules 中的模块</h2>
<h2>我的名字:{{$store.state.a.name}}</h2>
<button @click = "upMyName">修改名字</button>
<h3>getters :{{$store.getters.fullName}}</h3>
<h3>getters :{{$store.getters.fullName2}}</h3>
<h3>getters :{{$store.getters.fullName3}}</h3>
<button @click = "asyncName">异步修改名字</button>
</div>
</template>
<script>
import { ADDTOWNUM, YIBU } from '../store/mutation_type.js'
export default {
data() {
return {
}
},
methods: {
add() {
//提交 东西给store仓库
this.$store.commit('addEvent')
// console.log(111)
// console.log( this.$store.state.count)
},
sub() {
this.$store.commit('subEvent')
// console.log(222)
},
addNum(num) {
// this.$store.commit('addNum',num)
// 特殊的提交
this.$store.commit({
type: 'addNum',
// num:num
num,
age: 30
})
},
//发送问候
addStudents() {
let stu = { name: "chenbo", id: 52 }
this.$store.commit('addStu', stu)
},
updateName() {
this.$store.commit('updataName')
},
addName() {
this.$store.commit('addUserName')
},
deleteUser() {
this.$store.commit('deleteUser')
},
addTow() {
this.$store.commit(ADDTOWNUM)
},
editId() {
this.$store.commit(YIBU)
},
//异步修改数字
// handlerActionData (){
// this.$store.dispatch('actionDataFun',{
// message:'我是携带的信息,由内部执行完后打印',
// success:()=>{
// console.log('里面已经完成了!!!')
// }
// })//参数搞一个对象 success为回调函数 什么是回调函数? 就是一个方法执行完要调用的函数 现在函数作为参数传值 把这个函数传递过去 它会在某一时刻(触发)被执行就会它里面的要呈现的信息返回
// }
handlerActionData() {
this.$store.dispatch('actionDataFun', '我是携带的信息').then(
res=>{
console.log(this)
console.log('里面已经完成了!!!成功返回')
console.log(res)
},
// console.log(this),//root vue
// // 解决就是在外层定义一个that
// // let that = this,//不能再参数中定义 只能是语句
// function (res) {
// // console.log(this)//undefined ? why?
// console.log(this)//
// console.log('里面已经完成了!!!成功返回')
// }
)
},
upMyName(){
this.$store.commit('upMyName','lisa')
},
asyncName(){
// this.$store.dispatch('asyncName','大番薯')
this.$store.dispatch('asyncName')
}
},
}
</script>
<style>
</style>