Vuex 是一个专为 Vue.js应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。Vuex 也集成Vue 的官方调试工具 devtools extension (opens new window),提供了诸如零配置的 time-travel 调试、状态快照导入导出等高级调试功能。

npm i vue@3


// 引入vue
import Vue from "vue"
// 引入vuex
import Vuex from "vuex"
// 应用vuex
Vue.use(Vuex)
// 配置action
const action = {}
// 配置mutations
const mutations = {}
// 配置state
const state = {}
// 创建store
const store = new Vuex.Store({
action,
mutations,
state
})
// 暴露store
export default store
import store from './store/index'
new Vue({
el:'#app',
store,
render: h => h(App)
})
Count.vue
<template>
<div>
<h1>当前求和为:{{sum}}</h1>
<h3>放大十倍后:{{$store.getters.bigSum}}</h3>
<h4>我在{{school}}学习{{subject}}</h4>
<select v-model.number="n">
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
</select>
<button @click="addOne">+</button>
<button @click="lessOne">-</button>
<button @click="oddAddOne">奇数+</button>
<button @click="waitAddOne">待会儿加</button>
</div>
</template>
<script>
// 导入mapState
import {mapState} from 'vuex'
export default{
name:'App',
data(){
return {
n:1
}
},
computed:{
// sum(){
// return this.$store.state.sum
// },
// school(){
// return this.$store.state.school
// },
// subject(){
// return this.$store.state.subject
// }
...mapState({sum:'sum',school:'school',subject:'subject'})
},
methods:{
addOne(){
this.$store.dispatch('jia',this.n)
},
lessOne(){
this.$store.dispatch('jian',this.n)
},
oddAddOne(){
this.$store.dispatch('oddjia',this.n)
},
waitAddOne(){
this.$store.dispatch('waitjia',this.n)
}
},
mounted(){
// console.log(this);
}
}
</script>
<style>
.test1{
width: 200px;
height: 200px;
background: #ccc;
}
</style>
index.js
// 引入vue
import Vue from "vue"
// 引入vuex
import Vuex from "vuex"
// 应用vuex
Vue.use(Vuex)
// 配置action
const actions = {
jia(context,value){
console.log('action的jia被调用了');
context.commit('JIA',value)
},
jian(context,value){
console.log('action的jian被调用了');
context.commit('JIAN',value)
},
oddjia(context,value){
if(context.state.sum % 2){
context.commit('JIA',value)
}
},
waitjia(context,value){
setTimeout(()=>{
context.commit('JIA',value)
},500)
}
}
// 配置mutations
const mutations = {
JIA(state,value){
console.log('mutations的JIA被调用了',state,value);
state.sum += value
},
JIAN(state,value){
console.log('mutations的JIAN被调用了',state,value);
state.sum -= value
}
}
// 配置state
const state = {
sum:0,
school:'尚硅谷',
subject:'前端'
}
// 配置getter
const getters = {
bigSum(state){
return state.sum*10
}
}
// 创建store
const store = new Vuex.Store({
actions,
mutations,
state,
getters
})
// 暴露store
export default store
<h3>放大十倍后:{{$store.getters.bigSum}}</h3>
// 配置getter
const getters = {
bigSum(state){
return state.sum*10
}
}

跟mapState一样替换掉了被注释的代码,或者说是用这个方法生成了别替换掉的代码
// bigSum(){
// return this.$store.getters.bigSum
// },
...mapGetters({bigSum:'bigSum'})
点击事件后面的函数要传参数
<button @click="addOne(n)">+</button>
<button @click="lessOne(n)">-</button>
用mapMutations代替this.$store.commit()方法
commit传递的方法名和参数要在mutations里面操作所以这个方法叫做mapMutations
methods:{
// addOne(){
// this.$store.commit('JIA',this.n)
// },
// lessOne(){
// this.$store.commit('JIAN',this.n)
// },
...mapMutations({addOne:'JIA',lessOne:'JIAN'}), //模板里面的点击事件要穿value
}
<button @click="oddAddOne(n)">奇数+</button>
<button @click="waitAddOne(n)">待会儿加</button>
mapActions代替this.$store.dispatch()
dispatch传递的方法名和参数要在actions里面操作所以这个方法叫做mapActions
methods:{
// oddAddOne(){
// this.$store.dispatch('oddjia',this.n)
// },
// waitAddOne(){
// this.$store.dispatch('waitjia',this.n)
// }
...mapActions({oddAddOne:'oddjia',waitAddOne:'waitjia'})
},


npm i vue-router@3
再src下面创建router文件夹,然后创建一个index.js文件
index.js
import VueRouter from 'vue-router'
import Home from '../pages/Home'
import About from '../pages/About'
export default new VueRouter({
routes:[
{
path:'/home',
component:Home
},
{
path:'/about',
component:About
},
]
})
在main.js中引入路由并且注册路由,然后把router>index.js引入并且挂载
main.js
import Vue from 'vue'
import App from './App.vue'
Vue.config.productionTip = false
import VueRouter from 'vue-router'
import router from './router'
Vue.use(VueRouter)
new Vue({
el:'#app',
router:router,
render: h => h(App)
})
<router-link class="list" active-class="active" to="/About">About</router-link>
<router-link class="list" active-class="active" to="/Home">Home</router-link>
<router-view></router-view>
注意:
创建相关组件引入,然后在一级路由下写二级路由,注意不用加/
index.js
import VueRouter from 'vue-router'
import Home from '../pages/Home'
import About from '../pages/About'
import News from '../pages/News'
import Message from '../pages/Message'
export default new VueRouter({
routes:[
{
path:'/home',
component:Home,
// 二级路由不用加/
children:[
{
path:'News',
component:News
},
{
path:'Message',
component:Message
},
]
},
// 一级路由
{
path:'/about',
component:About
},
]
})
使用的时候to后面要加完整的路径
<template>
<div>
我是Home组件
<ul>
<router-link class="news-item" active-class="active" to="/home/News">News</router-link>
<router-link class="news-item" active-class="active" to='/home/Message'>Message</router-link>
</ul>
<div class='content'>
<router-view></router-view>
</div>
</div>
</template>
Message.vue
<template>
<div>
<ul>
<li v-for="m in messageList" :key="m.id">
<!-- 第一种写法:to的字符串写法 -->
<!-- <router-link :to="`/home/message/detail?id=${m.id}&title=${m.title}`">{{m.title}}</router-link> -->
<!-- 第二种写法:to的对象写法 -->
<router-link :to="{
path:'/home/message/detail',
query:{id:m.id,title:m.title}
}">
{{m.title}}</router-link>
</li>
<hr>
<router-view></router-view>
</ul>
</div>
</template>
<script>
export default{
name:'Message',
data(){
return {
messageList:[{
id:'001',title:'001消息'},
{id:'002',title:'002消息'},
{id:'003',title:'003消息'}
]
}
}
}
</script>
<style>
li{
list-style: none;
}
</style>
Detail.vue
2. Detail组件接收
<template>
<div>
<li>消息编号是:{{$route.query.id}}</li>
<li>消息标题是:{{$route.query.title}}</li>
<hr>
</div>
</template>
<script>
export default {
name:'About',
}
</script>
第一种to的字符串写法

第二种to的对象写法

第一种写法:props值为对象,该对象中所有的key-value的组合最终都会通过props传给Detail组件

第二种写法:props值为布尔值,布尔值为true,则把路由收到的所有params参数通过props传给Detail组件

第三种写法:props值为函数该函数返回的对象中每一组key-value都会通过props传给Detail组件


methods:{
back(){
this.$router.back()
},
forward(){
this.$router.forward()
},
go(){
// 传入的参数是正数,就往前走几步,
// 是负数就往后走几步
this.$router.go(3)
}
}
<keep-alive :include=["News",'Message']>
<router-view></router-view>
</keep-alive>
<keep-alive include="News">
<router-view></router-view>
</keep-alive>
activated(){
this.timer = setInterval(()=>{
this.opacity -= 0.01
if(this.opacity <= 0){
this.opacity = 1
}
},10)
console.log('组件被激活了');
},
deactivated(){
console.log('即将被销毁了');
clearInterval(this.timer)
}
router.beforeEach((to,from,next)=>{
console.log('前置路由守卫',to,from);
if(to.meta.isAuth){//判断是否 需要鉴权
if(localStorage.getItem('school') === '三河'){
next()
}
}else{next()}
})
// 全局后置路由守卫
router.afterEach((to,from)=>{
console.log('后置路由守卫',to,from);
document.title = to.meta.title
})
children:[
{
name:'xinwen',
path:'News',
component:News,
meta:{isAuth:true,title:'新闻'},
// 单独路由守卫
beforeEnter:(to,from,next)=>{
if(to.meta.isAuth){//判断是否 需要鉴权
if(localStorage.getItem('school') === '三河'){
next()
}
}else{next()}
}
},
beforeRouteEnter(to,from,next){
console.log('beforeRouteEnter组件内路由守卫',to,from);
if(to.meta.isAuth){//判断是否 需要鉴权
if(localStorage.getItem('school') === '三河'){
next()
}
}else{next()}
},
beforeRouteLeave(to,from,next){
console.log('beforeRouteLeave',to,from);
next()
}
省略