Vuex
作用:管理多個組件或者全局共享的狀態(tài)。
將復(fù)雜的玉凯、需要共享的邏輯處理放入actions中共享。
( 為什么在store中執(zhí)行Vue.use(Vuex)
,而不是在main.js中屡萤?
執(zhí)行順序問題。腳手架處理文件中的 import x from './yyy'
這類語句時掸宛,不管它們位置如何死陆,相當于放在文件開頭執(zhí)行。)
1.概念
在Vue中實現(xiàn)集中式狀態(tài)(數(shù)據(jù))管理的一個Vue插件唧瘾,對vue應(yīng)用中多個組件的共享狀態(tài)進行集中式的管理(讀/寫)措译,也是一種組件間通信的方式,且適用于任意組件間通信饰序。
2.何時使用领虹?
多個組件需要共享數(shù)據(jù)時
3.搭建vuex環(huán)境
- 創(chuàng)建文件:
src/store/index.js
//引入Vue核心庫
import Vue from 'vue'
//引入Vuex
import Vuex from 'vuex'
//應(yīng)用Vuex插件
Vue.use(Vuex)
//準備actions對象——響應(yīng)組件中用戶的動作
const actions = {}
//準備mutations對象——修改state中的數(shù)據(jù)
const mutations = {}
//準備state對象——保存具體的數(shù)據(jù)
const state = {}
//創(chuàng)建并暴露store
export default new Vuex.Store({
actions,
mutations,
state
})
- 在
main.js
中創(chuàng)建vm時傳入store
配置項
......
//引入store
import store from './store'
......
//創(chuàng)建vm
new Vue({
el:'#app',
render: h => h(App),
store
})
4.基本使用
- 初始化數(shù)據(jù)、配置
actions
求豫、配置mutations
塌衰,操作文件store.js
//引入Vue核心庫
import Vue from 'vue'
//引入Vuex
import Vuex from 'vuex'
//引用Vuex
Vue.use(Vuex)
const actions = {
//響應(yīng)組件中加的動作
jia(context,value){
// console.log('actions中的jia被調(diào)用了',miniStore,value)
context.commit('JIA',value)
},
}
const mutations = {
//執(zhí)行加
JIA(state,value){
// console.log('mutations中的JIA被調(diào)用了',state,value)
state.sum += value
}
}
//初始化數(shù)據(jù)
const state = {
sum:0
}
//創(chuàng)建并暴露store
export default new Vuex.Store({
actions,
mutations,
state,
})
- 組件中讀取vuex中的數(shù)據(jù):
$store.state.sum
- 組件中修改vuex中的數(shù)據(jù):
$store.dispatch('action中的方法名',數(shù)據(jù))
或$store.commit('mutations中的方法名',數(shù)據(jù))
備注:若沒有網(wǎng)絡(luò)請求或其他業(yè)務(wù)邏輯,組件中也可以越過actions蝠嘉,即不寫
dispatch
最疆,直接編寫commit
5.getters的使用
- 概念:當state中的數(shù)據(jù)需要經(jīng)過加工后再使用時,可以使用getters加工蚤告。(當處理過程需要復(fù)用時努酸。)
- 在
store.js
中追加getters
配置...... const getters = { bigSum(state){ return state.sum * 10 } } //創(chuàng)建并暴露store export default new Vuex.Store({ ...... getters })
- 組件中讀取數(shù)據(jù):
$store.getters.bigSum
6.四個map方法的使用
-
mapState方法:用于幫助我們映射
state
中的數(shù)據(jù)為計算屬性(不必在模板中寫$store.state.sum.xxx,也不必在computed中自己去寫多個方法返回數(shù)據(jù))杜恰。computed: { //借助mapState生成計算屬性:sum获诈、school、subject(對象寫法) ...mapState({sum:'sum',school:'school',subject:'subject'}), //借助mapState生成計算屬性:sum心褐、school烙荷、subject(數(shù)組寫法) ...mapState(['sum','school','subject']), },
-
mapGetters方法:用于幫助我們映射
getters
中的數(shù)據(jù)為計算屬性computed: { //借助mapGetters生成計算屬性:bigSum(對象寫法) ...mapGetters({bigSum:'bigSum'}), //借助mapGetters生成計算屬性:bigSum(數(shù)組寫法) ...mapGetters(['bigSum']) },
-
mapActions方法:用于幫助我們生成與
actions
對話的方法,即:包含$store.dispatch(xxx)
的函數(shù)methods:{ //靠mapActions生成:incrementOdd檬寂、incrementWait(對象形式) ...mapActions({incrementOdd:'jiaOdd',incrementWait:'jiaWait'}) //靠mapActions生成:incrementOdd终抽、incrementWait(數(shù)組形式) ...mapActions(['jiaOdd','jiaWait']) }
-
mapMutations方法:用于幫助我們生成與
mutations
對話的方法,即:包含$store.commit(xxx)
的函數(shù)methods:{ //靠mapActions生成:increment、decrement(對象形式) ...mapMutations({increment:'JIA',decrement:'JIAN'}), //靠mapMutations生成:JIA昼伴、JIAN(數(shù)組形式) ...mapMutations(['JIA','JIAN']), }
備注:mapActions與mapMutations使用時匾旭,若需要傳遞參數(shù)需要:在模板中綁定事件時傳遞好參數(shù),否則參數(shù)是事件對象圃郊。
7.模塊化+命名空間
- 目的:讓代碼更好維護价涝,讓多種數(shù)據(jù)分類更加明確。
- 修改
store.js
const countAbout = { namespaced:true,//開啟命名空間 state:{x:1}, mutations: { ... }, actions: { ... }, getters: { bigSum(state){ return state.sum * 10 } } } const personAbout = { namespaced:true,//開啟命名空間 state:{ ... }, mutations: { ... }, actions: { ... } } const store = new Vuex.Store({ modules: { countAbout, personAbout } })
- 開啟命名空間后持舆,組件中讀取state數(shù)據(jù):
//方式一:自己直接讀取 this.$store.state.personAbout.list //方式二:借助mapState讀壬瘛: ...mapState('countAbout',['sum','school','subject']),
- 開啟命名空間后,組件中讀取getters數(shù)據(jù):
//方式一:自己直接讀取 this.$store.getters['personAbout/firstPersonName'] //方式二:借助mapGetters讀纫菰ⅰ: ...mapGetters('countAbout',['bigSum'])
- 開啟命名空間后居兆,組件中調(diào)用dispatch
//方式一:自己直接dispatch this.$store.dispatch('personAbout/addPersonWang',person) //方式二:借助mapActions: ...mapActions('countAbout',{incrementOdd:'jiaOdd',incrementWait:'jiaWait'})
- 開啟命名空間后,組件中調(diào)用commit
//方式一:自己直接commit this.$store.commit('personAbout/ADD_PERSON',person) //方式二:借助mapMutations: ...mapMutations('countAbout',{increment:'JIA',decrement:'JIAN'}),
補充:
啟用module寫法竹伸,但不設(shè)置namespaced時:actions, mutations, getters 依然掛在全局泥栖,使用方式無變化。對于state:$store.state.a
勋篓。
此時使用mapState吧享,兩種寫法均報錯,原因不明譬嚣。
路由
- 理解: 一個路由(route)就是一組映射關(guān)系(key - value)钢颂,多個路由需要路由器(router)進行管理。
- 前端路由:key是路徑拜银,value是組件甸陌。
1.基本使用
- 安裝vue-router,命令:
npm i vue-router
- 應(yīng)用插件:
Vue.use(VueRouter)
- 編寫router配置項:
//引入VueRouter
import VueRouter from 'vue-router'
//引入Luyou 組件
import About from '../components/About'
import Home from '../components/Home'
//創(chuàng)建router實例對象盐股,去管理一組一組的路由規(guī)則
const router = new VueRouter({
routes:[
{
path:'/about',
component:About
},
{
path:'/home',
component:Home
}
]
})
//暴露router
export default router
- 實現(xiàn)切換(active-class可配置高亮樣式)
<router-link active-class="active" to="/about">About</router-link>
- 指定展示位置
<router-view></router-view>
2.幾個注意點
- 路由組件通常存放在
pages
文件夾钱豁,一般組件通常存放在components
文件夾。 - 通過切換疯汁,“隱藏”了的路由組件牲尺,默認是被銷毀掉的,需要的時候再去掛載幌蚊。
- 每個組件都有自己的
$route
屬性谤碳,里面存儲著自己的路由信息。 - 整個應(yīng)用只有一個router溢豆,可以通過組件的
$router
屬性獲取到蜒简。
3.多級路由(嵌套路由)
- 配置路由規(guī)則,使用children配置項:
routes:[
{
path:'/about',
component:About,
},
{
path:'/home',
component:Home,
children:[ //通過children配置子級路由
{
path:'news', //此處一定不要寫:/news
component:News
},
{
path:'message',//此處一定不要寫:/message
component:Message
}
]
}
]
- 跳轉(zhuǎn)(要寫完整路徑):
<router-link to="/home/news">News</router-link>
4.路由的query參數(shù)
- 傳遞參數(shù)
<!-- 跳轉(zhuǎn)并攜帶query參數(shù)漩仙,to的字符串寫法 -->
<router-link :to="/home/message/detail?id=666&title=你好">跳轉(zhuǎn)</router-link>
<!-- 跳轉(zhuǎn)并攜帶query參數(shù)搓茬,to的對象寫法 -->
<router-link
:to="{
path:'/home/message/detail',
query:{
id:666,
title:'你好'
}
}"
>跳轉(zhuǎn)</router-link>
- 接收參數(shù):
$route.query.id
$route.query.title
5.命名路由
1.作用:可以簡化路由的跳轉(zhuǎn)犹赖。
2.如何使用
(1).給路由命名:
{
path:'/demo',
component:Demo,
children:[
{
path:'test',
component:Test,
children:[
{
name:'hello', //給路由命名
path:'welcome',
component:Hello,
}
]
}
]
}
(2).簡化跳轉(zhuǎn):
<!--簡化前,需要寫完整的路徑 -->
<router-link to="/demo/test/welcome">跳轉(zhuǎn)</router-link>
<!--簡化后卷仑,直接通過名字跳轉(zhuǎn) -->
<router-link :to="{name:'hello'}">跳轉(zhuǎn)</router-link>
<!--簡化寫法配合傳遞參數(shù) -->
<router-link
:to="{
name:'hello',
query:{
id:666,
title:'你好'
}
}"
>跳轉(zhuǎn)</router-link>
6.路由的params參數(shù)
- 配置路由峻村,聲明接收params參數(shù)
{
path:'/home',
component:Home,
children:[
{
path:'news',
component:News
},
{
component:Message,
children:[
{
name:'xiangqing',
path:'detail/:id/:title', //使用占位符聲明接收params參數(shù)
component:Detail
}
]
}
]
}
- 傳遞參數(shù)
<!-- 跳轉(zhuǎn)并攜帶params參數(shù),to的字符串寫法 -->
<router-link :to="/home/message/detail/666/你好">跳轉(zhuǎn)</router-link>
<!-- 跳轉(zhuǎn)并攜帶params參數(shù)锡凝,to的對象寫法 -->
<router-link
:to="{
name:'xiangqing',
params:{
id:666,
title:'你好'
}
}"
>跳轉(zhuǎn)</router-link>
特別注意:路由攜帶params參數(shù)時粘昨,若使用to的對象寫法,則不能使用path配置項窜锯,必須使用name配置张肾!(為什么?)
- 接收參數(shù):
$route.params.id
$route.params.title
7.路由的props配置
作用:讓路由組件更方便的收到參數(shù)锚扎,直接從props中拿到xxx吞瞪,而不必寫$route.query.xxx (路由組件指作為頁面的組件)。
{
name:'xiangqing',
path:'detail/:id',
component:Detail,
//第一種寫法:props值為對象工秩,該對象中所有的key-value的組合最終都會通過props傳給Detail組件
// props:{a:900}
//第二種寫法:props值為布爾值,布爾值為true进统,則把路由收到的所有params參數(shù)通過props傳給Detail組件
// props:true
//第三種寫法:props值為函數(shù)助币,該函數(shù)返回的對象中每一組key-value都會通過props傳給Detail組件
props(route){
return {
id:route.query.id,
title:route.query.title
}
}
}
8.<router-link>
的replace屬性
- 作用:控制路由跳轉(zhuǎn)時操作瀏覽器歷史記錄的模式
- 瀏覽器的歷史記錄有兩種寫入方式:分別為
push
和replace
,push
是追加歷史記錄螟碎,replace
是替換當前記錄眉菱。路由跳轉(zhuǎn)時候默認為push
- 如何開啟
replace
模式:<router-link replace .......>News</router-link>
9.編程式路由導(dǎo)航
- 作用:不借助
<router-link>
實現(xiàn)路由跳轉(zhuǎn),讓路由跳轉(zhuǎn)更加靈活 - 具體編碼:
//$router的兩個API
this.$router.push({
name:'xiangqing',
params:{
id:xxx,
title:xxx
}
})
this.$router.replace({
name:'xiangqing',
params:{
id:xxx,
title:xxx
}
})
this.$router.forward() //前進
this.$router.back() //后退
this.$router.go() //可前進也可后退掉分,傳入數(shù)字
10.緩存路由組件
- 作用:讓不展示的路由組件保持掛載俭缓,不被銷毀川慌。(include屬性傳組件名躏结,即組件配置項中的name)
- 具體編碼:
<keep-alive include="News">
<router-view></router-view>
</keep-alive>
11.兩個新的生命周期鉤子
- 作用:路由組件所獨有的兩個鉤子嘉裤,用于捕獲路由組件的激活狀態(tài)播急。(路由切換至當前組件時激活挣饥,切換至其它組件時失活)
- 具體名字:
-
activated
路由組件被激活時觸發(fā)马昨。 -
deactivated
路由組件失活時觸發(fā)把曼。
-
12.路由守衛(wèi)
- 作用:對路由進行權(quán)限控制
- 分類:全局守衛(wèi)胡岔、獨享守衛(wèi)椿息、組件內(nèi)守衛(wèi)
- 全局守衛(wèi):
//全局前置守衛(wèi):初始化時執(zhí)行歹袁、每次路由切換前執(zhí)行
router.beforeEach((to,from,next)=>{
console.log('beforeEach',to,from)
if(to.meta.isAuth){ //判斷當前路由是否需要進行權(quán)限控制
if(localStorage.getItem('school') === 'atguigu'){ //權(quán)限控制的具體規(guī)則
next() //放行
}else{
alert('暫無權(quán)限查看')
// next({name:'guanyu'})
}
}else{
next() //放行
}
})
//全局后置守衛(wèi):初始化時執(zhí)行、每次路由切換后執(zhí)行
router.afterEach((to,from)=>{
console.log('afterEach',to,from)
if(to.meta.title){
document.title = to.meta.title //修改網(wǎng)頁的title
}else{
document.title = 'vue_test'
}
})
($route的meta項中可以放一些關(guān)于路由的自定義信息)
- 獨享守衛(wèi):
beforeEnter(to,from,next){
console.log('beforeEnter',to,from)
if(to.meta.isAuth){ //判斷當前路由是否需要進行權(quán)限控制
if(localStorage.getItem('school') === 'atguigu'){
next()
}else{
alert('暫無權(quán)限查看')
// next({name:'guanyu'})
}
}else{
next()
}
}
- 組件內(nèi)守衛(wèi):
//進入守衛(wèi):通過路由規(guī)則寝优,進入該組件時被調(diào)用
beforeRouteEnter (to, from, next) {
//
},
//離開守衛(wèi):通過路由規(guī)則条舔,離開該組件時被調(diào)用
beforeRouteLeave (to, from, next) {
}
(路由文件中的beforeEnter和組件內(nèi)的beforeRouteEnter區(qū)別之一是后者可以操作組件內(nèi)的data和methods等。
導(dǎo)航解析流程:先在路由配置里調(diào)用 beforeEnter乏矾,再在被激活的組件里調(diào)用 beforeRouteEnter孟抗,若前者未通過迁杨,則后者不會被調(diào)用)
13.路由器的兩種工作模式
- 對于一個url來說,什么是hash值夸浅?—— #及其后面的內(nèi)容就是hash值仑最。
- hash值不會包含在 HTTP 請求中,即:hash值不會帶給服務(wù)器帆喇。
- hash模式:
- 地址中永遠帶著#號警医,不美觀 。
- 若以后將地址通過第三方手機app分享坯钦,若app校驗嚴格预皇,則地址會被標記為不合法。
- 兼容性較好婉刀。
- history模式:
- 地址干凈吟温,美觀 。
- 兼容性和hash模式相比略差突颊。
- 應(yīng)用部署上線時需要后端人員支持鲁豪,解決刷新頁面服務(wù)端404的問題。(將所有對頁面的請求都返回index.html)