文章目录
1:基本使用
(1)安装
(1):npm
npm install vuex@next --save
2: yarn
yarn add vuex@next --save
安装成功后版本号应该是vuex: 4.0.2
(2):新建store文件夹
说明:module就是实际项目中为了更好的区分模块做到一个分割,里面新建了一个test的文件,里面会有state、mutation、action、getter四个核心模块,加上原本的module也就是vuex的五大核心模块。具体了解为什么使用module,请点击vuex官网module查看详细说明
src/store/index.ts
import { createStore } from "vuex";
import test from "./modules/test.ts";
export default createStore({
modules: {
test,
},
});
src/store/modules/test.ts
//示例
// state 仓库
const state = {
count: 0,
};
// getters 计算属性
const getters = {};
// actions 异步
const actions = {};
// mutations 同步
const mutations = {};
export default {
state,
getters,
actions,
mutations,
};
(3):注册(main.ts)
import { createApp } from 'vue'
import App from './App.vue'
import store from './store/index.ts' // 这个的路径要根据你自己写的位置
const app = createApp(App)
app.use(store).mount('#app');
(4):基本使用(获取state里面的值)
src/views/myHeader.vue
<template>
<div class="myHeader">>
<h1>值:{{ store.state.test.count }}</h1>
</div>
</template>
<script setup>
import { useStore } from "vuex";
const store = useStore();
</script>
<style scoped>
.myHeader {
width: 600px;
height: 200px;
border: 2px solid red;
margin: 0 auto;
}
</style>
(5):效果
2:核心使用
说明:用一个例子来讲解vuex的核心使用, 一个myHeader.vue用来做计算,有+1,-1,等一下加1,值大10倍,四个方法。
(1):获取值(实际项目中获取值)
思考一:在前面我有说到使用store.state.test.count来获取一个值,但是如果有多个值呢?每一个都要加上store.state.test这一串吗?一般人可能想到了使用结构赋值,例如\src\store\modules\test.ts中state中有以下数据
// state 仓库
const state = {
count: 0,
schoolName: "张三学校",
schoolSubject: "前端",
};
注意点1:在你使用结构赋值后,想到结构赋值会失去响应式,这样即使你改变了值也没有效果。所以需要将值使用toRefs包裹起来就可以了
// myHeader.vue
const { count, schoolName, schoolSubject} = toRefs(
store.state.test
);
(2):Mutation的使用-——同步(使用加1,减1两个方法说明)
1:代码
// myHeader.vue页面
<template>
<div class="myHeader">
<p>myHeader页面</p>
<p>值:{{ count }}</p>
<p style="color: red">学校名称:{{ schoolName }}</p>
<p style="color: red">学校科目:{{ schoolSubject }}</p>
<a-button @click="clickAdd()">+</a-button>
<a-button @click="clickReduce()">-</a-button>
</div>
</template>
<script setup>
import { toRefs } from "@vue/reactivity";
import { useStore, mapState, mapGetters, mapMutations, mapActions } from "vuex";
const store = useStore();
const { count, schoolName, schoolSubject} = toRefs(
store.state.test
);
// 加1方法
function clickAdd() {
store.commit("JIA");
}
// 减1方法
function clickReduce() {
store.commit("JIAN");
}
</script>
<style scoped>
.myHeader {
width: 600px;
height: 300px;
border: 2px solid red;
margin: 0 auto;
}
</style>
// /str/store/modules/test.ts
// mutations 同步
const mutations = {
/**
*
* @param state 必填 存储的仓库数据
* @param value 非必填 vue页面调用方法的参数
*/
JIA(state) {
state.count = state.count + 1;
},
JIAN(state) {
state.count = state.count - 1;
},
};
2:说明
注意点2:第二步的方法中store.commit(‘方法名’,参数),第三步的方法名,第二个就是第二步传过来的参数
(3):Action的使用——异步(使用等一会加方法模拟请求后获取数据的情况)
1:代码
// myHeader.vue页面
<template>
<div class="myHeader">
<p>myHeader页面</p>
<p>值:{{ count }}</p>
<a-button @click="clickSetTimeoutAdd()">等一会加</a-button>
</div>
</template>
<script setup>
import { toRefs } from "@vue/reactivity";
import { useStore, mapState, mapGetters, mapMutations, mapActions } from "vuex";
const store = useStore();
const { count, schoolName, schoolSubject} = toRefs(
store.state.test
);
// 等一会加方法
function clickSetTimeoutAdd() {
store.dispatch("jia2");
}
</script>
// /str/store/modules/test.ts
// actions 异步
const actions = {
jia2(content, value) {
setTimeout(() => {
content.commit("JIA", value);
}, 1000);
},
};
2:说明
注意点3:
(1)首先让外面看看vuex官网的vuex状态更改的流程图(主要讲解以下红框部分)
(2)简单说明:vc通过dispatch进入action,调用方法commit进入mutations,那么我在说明mutations的时候为什么直接跳过了dispatch进入action呢?举个简单例子,客人去饭店吃饭,先找服务员点餐(action),服务员找厨师说做这个(mutations),但是,客人如果经常来饭店,是不是可以直接和厨师说我要吃xxx,这就是看实际开发中需不需要尽力这一步,而这异步就是看你是否需要异步操作决定的。
(4):Getter的使用——计算属性(通过页面显示的值放大十倍的方法来讲解)
1:代码
// myHeader.vue页面
<template>
<div class="myHeader">
<p>myHeader页面</p>
<p>值:{{ count }}</p>
<p>值大10倍:{{ bigSum() }}</p>
</div>
</template>
<script setup>
import { toRefs } from "@vue/reactivity";
import { useStore, mapState, mapGetters, mapMutations, mapActions } from "vuex";
const store = useStore();
const { count, schoolName, schoolSubject} = toRefs(
store.state.test
);
// 值大10倍方法
function bigSum() {
return store.getters.bigSum;
}
</script>
// /str/store/modules/test.ts
// getters 计算属性
const getters = {
bigSum(state) {
console.log("getters", state);
return state.count * 10;
},
};
2:说明
(5):最后附上完整代码
(1) src\store\index.ts
import { createStore } from "vuex";
import test from "./modules/test.ts";
export default createStore({
modules: {
test,
},
});
(2)src\store\modules\test.ts
//示例
// state 仓库
const state = {
count: 0,
schoolName: "张三学校",
schoolSubject: "前端",
personlist: [
{
id: "001",
name: "张三",
age: 18,
},
{
id: "002",
name: "李四",
age: 19,
},
{
id: "003",
name: "王五",
age: 20,
},
],
};
// getters 计算属性
const getters = {
bigSum(state) {
console.log("getters", state);
return state.count * 10;
},
};
// actions 异步
const actions = {
jia2(content, value) {
setTimeout(() => {
content.commit("JIA", value);
}, 1000);
},
};
// mutations 同步
const mutations = {
/**
*
* @param state 必填 存储的仓库数据
* @param value 非必填 vue页面调用方法的参数
*/
JIA(state) {
state.count = state.count + 1;
},
JIAN(state) {
state.count = state.count - 1;
},
};
export default {
state,
getters,
actions,
mutations,
};
(3)myHeader.vue
<template>
<div>
<h1>求和:{{ sum }}</h1>
<h1>求和的值大10倍:{{ bigSum }}</h1>
<h1>学校名称:{{ schoolName }}</h1>
<h1>学校科目:{{ schoolSubject }}</h1>
<select v-model.number="n">
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
</select>
<button @click="add1(n)">+</button>
<button @click="deSum(n)">-</button>
<button @click="addSum2(n)">奇数相加</button>
<button @click="addSum3(n)">等一会加</button>
<hr />
<son
:clickFatherone="clickFatherone()"
@clickFathertwo="clickFathertwo()"
/>
</div>
</template>
<script>
// import nanoid from 'nanoid'
import { mapState, mapGetters, mapMutations, mapActions } from "vuex";
import son from "./son.vue";
export default {
props: ["addTodo"],
components: {
son,
},
data() {
return {
// sum: 0,
n: 1,
};
},
computed: {
// 方法1:页面渲染vuex数据
// sum(){
// return this.$store.state.sum
// },
// schoolName(){
// return this.$store.state.schoolName
// },
// schoolSubject(){
// return this.$store.state.schoolSubject
// },
// bigSum(){
// return this.$store.getters.bigSum
// },
/**
* 第二种方法,vuex提供的四个map方法 第一个是数据名,第二个是仓库(store)里面的数据名
*/
// ...mapState({sum:'sum',schoolName:'schoolName',schoolSubject:'schoolSubject'}),
// ...mapGetters({bigSum:'bigSum'}),
/**
* 第三种方法,在第二种的上面(数据名和仓库名一样)使用简写
* 注意:是字符串的
*/
...mapState(["sum", "schoolName", "schoolSubject", "personlist"]),
...mapGetters(["bigSum"]),
},
methods: {
// 第一种方法:同数据
// add1() {
// // this.sum += this.n;
// this.$store.commit('JIA',this.n)
// },
// deSum() {
// // this.sum -= this.n;
// this.$store.commit('JIAN',this.n)
// },
// addSum2() {
// this.$store.dispatch('addSum2',this.n)
// },
// addSum3() {
// this.$store.dispatch('addSum3',this.n)
// },
// 第二种方法,
...mapMutations({ add1: "JIA", deSum: "JIAN" }),
...mapActions({ addSum2: "addSum2", addSum3: "addSum3" }),
// 第三种方法,使用数据简写,同上
clickFatherone(params) {
console.log("父组件的方法被触发了one", params);
},
clickFathertwo(params) {
console.log("父组件的方法被触发了two", params);
},
},
mounted() {
console.log("header", this);
},
};
</script>
<style scoped></style>