vue-axios-vuex-全家桶
Github來(lái)源: | 求星星 ? | 給個(gè)??關(guān)注,??點(diǎn)贊,??鼓勵(lì)一下作者
https://1024bibi.com/2021/09/01/vue-axios-vuex-%E5%85%A8%E5%AE%B6%E6%A1%B6/

axios
Axios 是一個(gè)基于 promise 的 HTTP 庫(kù),可以用在瀏覽器和 node.js 中。簡(jiǎn)單來(lái)說(shuō)就是前端最火最簡(jiǎn)單的一個(gè)http請(qǐng)求解決方案。
功能
從瀏覽器中創(chuàng)建 XMLHttpRequests 從 node.js 創(chuàng)建 http 請(qǐng)求 支持 Promise API 攔截請(qǐng)求和響應(yīng) 轉(zhuǎn)換請(qǐng)求數(shù)據(jù)和響應(yīng)數(shù)據(jù) 取消請(qǐng)求 自動(dòng)轉(zhuǎn)換 JSON 數(shù)據(jù) 客戶端支持防御 XSRF
代碼封裝
工具類封裝
// 引入axios
import axios from 'axios';
// 創(chuàng)建axios實(shí)例
const httpService = axios.create({
// url前綴-'https://some-domain.com/api/'
baseURL: process.env.BASE_API, // 需自定義
// 請(qǐng)求超時(shí)時(shí)間
timeout: 3000 // 需自定義
});
// request攔截器
httpService.interceptors.request.use(
config => {
// 根據(jù)條件加入token-安全攜帶
if (true) { // 需自定義
// 讓每個(gè)請(qǐng)求攜帶token
config.headers['User-Token'] = '';
}
return config;
},
error => {
// 請(qǐng)求錯(cuò)誤處理
Promise.reject(error);
}
)
// respone攔截器
httpService.interceptors.response.use(
response => {
// 統(tǒng)一處理狀態(tài)
const res = response.data;
if (res.statuscode != 1) { // 需自定義
// 返回異常
return Promise.reject({
status: res.statuscode,
message: res.message
});
} else {
return response.data;
}
},
// 處理處理
error => {
if (error && error.response) {
switch (error.response.status) {
case 400:
error.message = '錯(cuò)誤請(qǐng)求';
break;
case 401:
error.message = '未授權(quán),請(qǐng)重新登錄';
break;
case 403:
error.message = '拒絕訪問(wèn)';
break;
case 404:
error.message = '請(qǐng)求錯(cuò)誤,未找到該資源';
break;
case 405:
error.message = '請(qǐng)求方法未允許';
break;
case 408:
error.message = '請(qǐng)求超時(shí)';
break;
case 500:
error.message = '服務(wù)器端出錯(cuò)';
break;
case 501:
error.message = '網(wǎng)絡(luò)未實(shí)現(xiàn)';
break;
case 502:
error.message = '網(wǎng)絡(luò)錯(cuò)誤';
break;
case 503:
error.message = '服務(wù)不可用';
break;
case 504:
error.message = '網(wǎng)絡(luò)超時(shí)';
break;
case 505:
error.message = 'http版本不支持該請(qǐng)求';
break;
default:
error.message = `未知錯(cuò)誤${error.response.status}`;
}
} else {
error.message = "連接到服務(wù)器失敗";
}
return Promise.reject(error);
}
)
/*網(wǎng)絡(luò)請(qǐng)求部分*/
/*
* get請(qǐng)求
* url:請(qǐng)求地址
* params:參數(shù)
* */
export function get(url, params = {}) {
return new Promise((resolve, reject) => {
httpService({
url: url,
method: 'get',
params: params
}).then(response => {
resolve(response);
}).catch(error => {
reject(error);
});
});
}
/*
* post請(qǐng)求
* url:請(qǐng)求地址
* params:參數(shù)
* */
export function post(url, params = {}) {
return new Promise((resolve, reject) => {
httpService({
url: url,
method: 'post',
data: params
}).then(response => {
resolve(response);
}).catch(error => {
reject(error);
});
});
}
/*
* 文件上傳
* url:請(qǐng)求地址
* params:參數(shù)
* */
export function fileUpload(url, params = {}) {
return new Promise((resolve, reject) => {
httpService({
url: url,
method: 'post',
data: params,
headers: { 'Content-Type': 'multipart/form-data' }
}).then(response => {
resolve(response);
}).catch(error => {
reject(error);
});
});
}
export default {
get,
post,
fileUpload
}
使用
// 引入工具類-目錄自定義
import fetch from '@/util/fetch'
// 使用
const TMPURL = ''; // url地址
const params = {}; // 參數(shù)
fetch.post(TMPURL + '/login/login', params);
vuex是什么?
vuex是一個(gè)專為 Vue.js 應(yīng)用程序開(kāi)發(fā)的狀態(tài)管理模式。它采用集中式存儲(chǔ)管理應(yīng)用的所有組件的狀態(tài),并以相應(yīng)的規(guī)則保證狀態(tài)以一種可預(yù)測(cè)的方式發(fā)生變化。chrome安裝調(diào)試工具 devtools extension
單向數(shù)據(jù)流

示意圖說(shuō)明:
State:驅(qū)動(dòng)應(yīng)用的數(shù)據(jù)源(單向數(shù)據(jù)流) View:以聲明方式將 state 映射到視圖(靜態(tài)顯示出來(lái)的數(shù)據(jù)源) Actions:處理用戶在view上面操作而導(dǎo)致的狀態(tài)變化(數(shù)據(jù)源變化追蹤)
一個(gè)簡(jiǎn)單的demo案例:
<template>
<div>
<!-- view -->
<div>{{ count }}</div>
<button @click="increment">increment</button>
</div>
</template>
<script>
export default {
// state
data () {
return {
count: 0
}
},
// actions
methods: {
increment () {
this.count++
}
}
}
</script>
<style>
</style>
vuex解決的問(wèn)題
多個(gè)視圖組件,包括父子組件,兄弟組件之間的狀態(tài)共享 不同視圖組件的行為需要變更同一個(gè)狀態(tài)
vuex使用場(chǎng)景
中大型單頁(yè)應(yīng)用,需要考慮如何更好地在組件外部管理狀態(tài),簡(jiǎn)單應(yīng)用不建議使用
vuex與全局變量的區(qū)別
響應(yīng)式:vuex的狀態(tài)存儲(chǔ)是響應(yīng)式的,當(dāng)Vue組件從store中讀取狀態(tài)的時(shí)候,若store中的狀態(tài)發(fā)生變化,那么相應(yīng)的組件也會(huì)得到高效更新 不能直接改變store:不能直接改變store的變化,改變store中狀態(tài)的唯一途徑是commit mutation,方便于跟蹤每一個(gè)狀態(tài)的變化
vuex核心流程

示意圖說(shuō)明:
Vue Components:Vue組件。HTML頁(yè)面上,負(fù)責(zé)接收用戶操作等交互行為,執(zhí)行dispatch方法觸發(fā)對(duì)應(yīng)action進(jìn)行回應(yīng) Dispatch:操作行為觸發(fā)方法,是唯一能執(zhí)行action的方法 Actions:操作行為處理模塊。負(fù)責(zé)處理Vue Components接收到的所有交互行為。包含同步/異步操作,支持多個(gè)同名方法,按照注冊(cè)的順序依次觸發(fā)。向后臺(tái)API請(qǐng)求的操作就在這個(gè)模塊中進(jìn)行,包括觸發(fā)其他action以及提交mutation的操作。該模塊提供了Promise的封裝,以支持action的鏈?zhǔn)接|發(fā) Commit:狀態(tài)改變提交操作方法。對(duì)mutation進(jìn)行提交,是唯一能執(zhí)行mutation的方法 Mutations:狀態(tài)改變操作方法。是Vuex修改state的唯一推薦方法,其他修改方式在嚴(yán)格模式下將會(huì)報(bào)錯(cuò)。該方法只能進(jìn)行同步操作,且方法名只能全局唯一。操作之中會(huì)有一些hook暴露出來(lái),以進(jìn)行state的監(jiān)控等 State:頁(yè)面狀態(tài)管理容器對(duì)象。集中存儲(chǔ)Vue components中data對(duì)象的零散數(shù)據(jù),全局唯一,以進(jìn)行統(tǒng)一的狀態(tài)管理。頁(yè)面顯示所需的數(shù)據(jù)從該對(duì)象中進(jìn)行讀取,利用Vue的細(xì)粒度數(shù)據(jù)響應(yīng)機(jī)制來(lái)進(jìn)行高效的狀態(tài)更新 Getters:state對(duì)象讀取方法。圖中沒(méi)有單獨(dú)列出該模塊,應(yīng)該被包含在了render中,Vue Components通過(guò)該方法讀取全局state對(duì)象
總結(jié)說(shuō)明:
Vue組件接收交互行為,調(diào)用dispatch方法觸發(fā)action相關(guān)處理,若頁(yè)面狀態(tài)需要改變,則調(diào)用commit方法提交mutation修改state,通過(guò)getters獲取到state新值,重新渲染Vue Components,界面隨之更新
安裝
npm install vuex --save
簡(jiǎn)單示例
(1)src/vuex/store.js中寫(xiě)入以下代碼:
// 引入vue
import Vue from 'vue'
// 引入vuex
import Vuex from 'vuex'
// 使用vuex
Vue.use(Vuex)
// 1、state:創(chuàng)建初始化狀態(tài)
const state = {
// 放置初始狀態(tài)
count: 1
}
// 2、mutations:創(chuàng)建改變狀態(tài)的方法
const mutations = {
// 狀態(tài)變更函數(shù)-一般大寫(xiě)
ADD (state, n) {
state.count += n;
}
}
// 3、getters:提供外部獲取state
const getters = {
count: function(state){
return state.count;
}
}
// 4、actions:創(chuàng)建驅(qū)動(dòng)方法改變mutations
const actions ={
// 觸發(fā)mutations中相應(yīng)的方法-一般小寫(xiě)
add ({commit}, data) {
commit('ADD', data)
}
}
// 5、全部注入Store中
const store = new Vuex.Store({
state,
mutations,
getters,
actions
});
// 6、輸出store
export default store;
代碼說(shuō)明:
state - mutations - getters - actions - store,以上寫(xiě)法基本固定。 小型項(xiàng)目用上面的簡(jiǎn)單管理狀態(tài)即可。
(2)src/main.js代碼中
import Vue from 'vue'
import App from './App'
import router from './router'
// 引入store
import store from './vuex/store'
Vue.config.productionTip = false
/* eslint-disable no-new */
new Vue({
el: '#app',
router,
store, // 全局注入
components: { App },
template: '<App/>'
})
(3)src/compontent/Count.vue頁(yè)面組件中代碼如下:
<template>
<div class="hello">
<h1>{{ msg }}</h1>
<h2>{{count}}</h2>
<button @click="clickAdd">新增</button>
</div>
</template>
<script>
export default {
data () {
return {
msg: 'Vuex test!'
}
},
computed: {
// 獲取state值
count() {
return this.$store.state.count;
}
},
methods: {
clickAdd() {
//分發(fā)action中的add方法
this.$store.dispatch('add', 1);
}
}
}
</script>
<style scoped>
</style>
狀態(tài)對(duì)象的獲取方法
在組件的template中直接使用
<h2>{{ $store.state.count }}</h2>
在計(jì)算屬性computed中直接賦值
// 方式1:直接獲取
computed: {
count() {
// this指的是main.js中的vue實(shí)例對(duì)象
return this.$store.state.count;
}
}
通過(guò)mapState的對(duì)象來(lái)賦值
// 方式2:利用mapState
computed: mapState({
// es5寫(xiě)法
count: function (state) {
return state.count;
},
// es6寫(xiě)法
count: state => state.count
})
通過(guò)mapState的數(shù)組來(lái)賦值
// 方式3:數(shù)組獲取
computed: mapState(['count'])
通過(guò)mapState的JSON來(lái)賦值
// 方式4:JSON獲取
computed: mapState({
count: 'count'
})
mutations-getters-actions異步
mutations(修改狀態(tài))
(1)template中直接使用$store.commit( )觸發(fā)
// template
<button @click="$store.commit('ADD')">+</button>
// src/vuex/store.js
const mutations = {
// 狀態(tài)變更函數(shù)
ADD (state) {
state.count++;
}
}
(2)利用mapMutations引入觸發(fā)
<template>
<div class="hello">
<h1>{{ msg }}</h1>
<h2>{{count}}</h2>
<!-- 3、、直接調(diào)用相應(yīng)的方法 -->
<button @click="ADD">+</button>
</div>
</template>
<script>
// 1、引入mapMutations
import {mapState, mapMutations} from 'vuex'
export default {
data () {
return {
msg: 'Vuex test!'
}
},
// 通過(guò)mapState的JSON來(lái)賦值
computed: mapState({
count: 'count'
}),
// 2、methods中加入mapMutations
methods: mapMutations([
'ADD'
])
}
</script>
<style scoped>
</style>
getters(獲取state和過(guò)濾)
(1)基本用法
// src/vuex/store.js
const getters = {
count: function(state){
// 返回加上100
return state.count + 100;
}
}
(2)常規(guī)獲取值
computed: {
// 獲取getters
count(){
return this.$store.getters.count;
}
}
(3)mapGetters獲取值
// 1、引入mapMutations
import {mapState, mapMutations, mapGetters} from 'vuex'
// 2、使用
computed: {
// 獲取getters
...mapGetters(["count"])
}
actions(異步狀態(tài)修改)
actions和mutations功能基本一樣,不同點(diǎn)是,actions是異步的改變state狀態(tài),而mutations是同步改變狀態(tài)。不過(guò)實(shí)際項(xiàng)目中一般都是通過(guò)actions改變mutations中的值。
(1)store.js中增加異步代碼
// src/vuex/store.js
const actions ={
// 觸發(fā)mutations中相應(yīng)的方法
add ({commit}) {
// 增加異步
setTimeout(()=>{
commit('ADD')
},3000);
console.log('我比reduce提前執(zhí)行');
}
}
(2)常規(guī)使用
// template
<button @click="add">+</button>
// script
methods: {
add() {
//分發(fā)action
this.$store.dispatch('add');
}
}
(3)mapActions的使用
// template
<button @click="add">+</button>
// script
// 引入mapActions
import {mapState, mapActions} from 'vuex'
// 使用mapActions
methods: {
...mapActions(['add'])
}
傳遞參數(shù)
只需要在mutations和actions相應(yīng)的地方加上參數(shù),然后調(diào)用的時(shí)候傳入即可。
(1)src/vuex/store.js中
// actions中傳遞參數(shù)
const mutations = {
ADD (state, n) {
state.count += n;
}
}
// actions中傳遞參數(shù)
const actions ={
// 觸發(fā)mutations中相應(yīng)的方法
add ({commit}, n) {
// 增加異步
setTimeout(()=>{
commit('ADD', n);
},3000);
console.log('我比reduce提前執(zhí)行');
}
}
(2)頁(yè)面組件常規(guī)調(diào)用傳遞
// template
<button @click="add">+</button>
// script
methods: {
add() {
// 分發(fā)action
this.$store.dispatch('add', 99);
}
}
(3)頁(yè)面組件使用mapActions調(diào)用傳遞
// template
<button @click="add(99)">+</button>
// script
methods: {
...mapActions(['add'])
}
module-模塊組
當(dāng)應(yīng)用非常復(fù)雜,狀態(tài)非常多的時(shí)候,需要將store 分割成模塊(module)。每個(gè)模塊擁有自己的 state、mutation、action、getter、甚至是嵌套子模塊,從上至下進(jìn)行同樣方式的分割。
大致的結(jié)構(gòu)
// 模塊A
const moduleA = {
state: { ... },
mutations: { ... },
actions: { ... },
getters: { ... }
}
// 模塊B
const moduleB = {
state: { ... },
mutations: { ... },
actions: { ... }
}
// 組裝
const store = new Vuex.Store({
modules: {
a: moduleA,
b: moduleB
}
})
// 取值
store.state.a // -> moduleA 的狀態(tài)
store.state.b // -> moduleB 的狀態(tài)
實(shí)際開(kāi)發(fā)中建議把module分開(kāi)編寫(xiě)。
(1)src/vuex/module1.js
// 模塊1
const module1 = {
// 初始化狀態(tài)
state: {
module1: {
name: '模塊1'
}
},
// 編寫(xiě)動(dòng)作
mutations: {
CHANGE1 (state, data) {
state.module1 = data;
}
},
// 取值
getters: {
module1: function(state){
return state.module1;
}
},
// 創(chuàng)建驅(qū)動(dòng),可異步
actions: {
change1 ({commit}, data) {
commit('CHANGE1', data)
}
}
}
export default module1;
(2)src/vuex/module2.js
// 模塊1
const module2 = {
// 初始化狀態(tài)
state: {
module2: {
name: '模塊2'
}
},
// 編寫(xiě)動(dòng)作
mutations: {
CHANGE2 (state, data) {
state.module2 = data;
}
},
// 取值
getters: {
module2: function(state){
return state.module2;
}
},
// 創(chuàng)建驅(qū)動(dòng),可異步
actions: {
change2 ({commit}, data) {
commit('CHANGE2', data)
}
}
}
export default module2;
(3)src/vuex/store.js
// 引入vue
import Vue from 'vue'
// 引入vuex
import Vuex from 'vuex'
// 引入module1
import module1 from '@/vuex/module1'
// 引入module2
import module2 from '@/vuex/module2'
// 使用vuex
Vue.use(Vuex)
// 模塊注入
const store = new Vuex.Store({
modules: {
a: module1,
b: module2
}
})
// 輸出store
export default store;
(4)組件中使用,src/compontent/one.vue
<template>
<div id="app">
<!-- module1 -->
<h2>{{ module1.name }}</h2>
<button @click="change1({'name': 'change1'})">module1改變</button>
<!-- module2 -->
<h2>{{ module2.name }}</h2>
<button @click="change2({'name': 'change2'})">module2改變</button>
</div>
</template>
<script>
// 引入快捷方法
import {mapState, mapGetters, mapActions} from 'vuex'
export default {
name: 'app',
data () {
return {
}
},
computed:{
// mapState取值
// ...mapState({
// module1: state => state.a.module1.name,
// module2: state => state.b.module2.name
// })
// mapGetter取值
...mapGetters(['module1', 'module2'])
},
methods: {
// mapAction取方法
...mapActions([
'change1',
'change2'
])
}
}
</script>
<style>
</style>
PS:module中命名要唯一,不然獲取值和改變值的時(shí)候會(huì)沖突,目前親測(cè)mapGetters只能獲取對(duì)象。
vue-router
Vue Router 是 Vue.js 官方的路由管理器。它和 Vue.js 的核心深度集成,讓構(gòu)建單頁(yè)面應(yīng)用變得易如反掌。
包含的功能有:
嵌套的路由/視圖表 模塊化的、基于組件的路由配置 路由參數(shù)、查詢、通配符 基于 Vue.js 過(guò)渡系統(tǒng)的視圖過(guò)渡效果 細(xì)粒度的導(dǎo)航控制 帶有自動(dòng)激活的 CSS class 的鏈接 HTML5 歷史模式或 hash 模式,在 IE9 中自動(dòng)降級(jí) 自定義的滾動(dòng)條行為
安裝
使用命令安裝:
npm install vue-router --save
在src/router/index.js文件中
// 引入vue框架
import Vue from 'vue'
// 引入vue-router路由依賴
import Router from 'vue-router'
// 引入頁(yè)面組件,命名為HelloWorld
import HelloWorld from '@/components/HelloWorld'
// Vue全局使用Router
Vue.use(Router)
// 定義路由配置
export default new Router({
routes: [ //配置路由,這里是個(gè)數(shù)組
{ //每一個(gè)鏈接都是一個(gè)對(duì)象
path: '/', //鏈接路徑
name: 'HelloWorld', //路由名稱,
component: HelloWorld //對(duì)應(yīng)的組件模板
}
]
})
在系統(tǒng)入口文件main.js中注入router,代碼如下:
// 引入vue框架
import Vue from 'vue'
// 引入根組件
import App from './App'
// 引入路由配置
import router from './router'
// 關(guān)閉生產(chǎn)模式下給出的提示
Vue.config.productionTip = false
// 定義實(shí)例
new Vue({
el: '#app',
router, // 注入框架中
components: { App },
template: '<App/>'
})
頁(yè)面跳轉(zhuǎn)
router-link標(biāo)簽跳轉(zhuǎn)
在html標(biāo)簽內(nèi)使用router-link跳轉(zhuǎn),相應(yīng)于超鏈接a標(biāo)簽,使用方式如下:
<router-link to="/">[顯示字段]</router-link>
to:導(dǎo)航路徑
使用示例如下:
<p>導(dǎo)航 :
<router-link to="/">首頁(yè)</router-link>
<router-link to="/hello">hello</router-link>
</p>
編程式導(dǎo)航-JS代碼內(nèi)部跳轉(zhuǎn)
實(shí)際項(xiàng)目中,很多時(shí)候都是通過(guò)在JS代碼內(nèi)部進(jìn)行導(dǎo)航的跳轉(zhuǎn),使用方式如下:
this.$router.push('/xxx')
具體的簡(jiǎn)單用法:
(1)先編寫(xiě)一個(gè)按鈕,在按鈕上綁定goHome( )方法。
<button @click="goHome">回到首頁(yè)</button>
(2)在<script>模塊里加入goHome方法,并用this.$router.push(‘/’)導(dǎo)航到首頁(yè)
export default {
name: 'app',
methods: {
goHome(){
this.$router.push('/home');
}
}
}
其他常用方法
// 后退一步記錄,等同于 history.back()
this.$router.go(-1)
// 在瀏覽器記錄中前進(jìn)一步,等同于 history.forward()
this.$router.go(1)
子路由-路由嵌套
子路由,也叫路由嵌套,采用在children后跟路由數(shù)組來(lái)實(shí)現(xiàn),數(shù)組里和其他配置路由基本相同,需要配置path和component,然后在相應(yīng)部分添加
src/components/Home.vue(父頁(yè)面)
<template>
<div class="hello">
<h1>{{ msg }}</h1>
<!-- 添加子路由導(dǎo)航 -->
<p>導(dǎo)航 :
<router-link to="/home">首頁(yè)</router-link> |
<router-link to="/home/one">-子頁(yè)面1</router-link> |
<router-link to="/home/two">-子頁(yè)面2</router-link>
</p>
<!-- 子頁(yè)面展示部分 -->
<router-view/>
</div>
</template>
<script>
export default {
name: 'Home',
data () {
return {
msg: 'Home Page!'
}
}
}
</script>
<style scoped>
</style>
src/components/One.vue(子頁(yè)面1)
<template>
<div class="hello">
<h1>{{ msg }}</h1>
</div>
</template>
<script>
export default {
name: 'One',
data () {
return {
msg: 'Hi, I am One Page!'
}
}
}
</script>
<style scoped>
</style>
src/components/Two.vue(子頁(yè)面2)
<template>
<div class="hello">
<h1>{{ msg }}</h1>
</div>
</template>
<script>
export default {
name: 'Two',
data () {
return {
msg: 'Hi, I am Two Page!'
}
}
}
</script>
<style scoped>
</style>
src/router/index.js(路由配置)
import Vue from 'vue'
import Router from 'vue-router'
import Home from '@/components/Home'
import One from '@/components/One'
import Two from '@/components/Two'
Vue.use(Router)
export default new Router({
routes: [
{
path: '/', // 默認(rèn)頁(yè)面重定向到主頁(yè)
redirect: '/home'
},
{
path: '/home', // 主頁(yè)路由
name: 'Home',
component: Home,
children:[ // 嵌套子路由
{
path:'one', // 子頁(yè)面1
component:One
},
{
path:'two', // 子頁(yè)面2
component:Two
},
]
}
]
})
路由傳遞參數(shù)
通過(guò)<router-link> 標(biāo)簽中的to傳參
基本語(yǔ)法:
<router-link :to="{name:xxx, params: {key:value}}">valueString</router-link>
PS:上面to前邊是帶冒號(hào),后邊跟的是一個(gè)對(duì)象形勢(shì)的字符串
name:在路由配置文件中起的name值。叫做命名路由。 params:要傳的參數(shù),它是對(duì)象形式,在對(duì)象里可以傳遞多個(gè)值。
具體實(shí)例如下:
(1)在src/components/Home.vue里面導(dǎo)航中添加如下代碼:
<router-link :to="{name: 'one', params:{username:'test123'}}">子頁(yè)面1</router-link>
(2)在src/router/indes.js中添加如下代碼,重點(diǎn)是name:
{
path:'one', // 子頁(yè)面1
name: 'one', // 路由名稱-命名路由
component:One
}
(3)在src/components/One.vue里面接受參數(shù),代碼如下:
<h2>{{$route.params.username}}</h2>
url中傳遞參數(shù)
(1)在路由中以冒號(hào)傳遞,在src/router/index.js中加入如下代碼:
{
path:'/home/two/:id/:name', // 子頁(yè)面2
component:Two
},
(2)接受參數(shù),在src/components/Two.vuez中加入如下代碼:
<p>ID:{{ $route.params.id}}</p>
<p>名稱:{{ $route.params.name}}</p>
(3)路由跳轉(zhuǎn),在src/components/Home.vue中加入如下代碼:
<router-link to="/home/two/1/張三">子頁(yè)面2</router-link>
PS:to前沒(méi)有冒號(hào)為字符串路由,必須全部匹配。
(4)如果路由參數(shù)需要有特定的規(guī)則,就需要加入正則表達(dá)式了,示例如下:
{
path:'/home/two/:id(\d+)/:name', // 子頁(yè)面2
component:Two
}
編程式導(dǎo)航-params傳遞參數(shù)
(1)在src/router/index.js頁(yè)面加入如下代碼:
{
path:'/home/three', // 子頁(yè)面3
name: 'three',
component:Three
}
(2)在src/components/Three.vue頁(yè)面加入如下代碼:
<p>ID:{{ $route.params.id}}</p>
<p>名稱:{{ $route.params.name}}</p>
(3)在src/components/Home.vue中加入如下代碼:
// template
<button @click="toThreePage">頁(yè)面3-params傳參</button>
// script
methods: {
toThreePage() {
this.$router.push({name: 'three', params: {id: 1, name: 'zhangsan'}})
}
}
說(shuō)明:
A、動(dòng)態(tài)路由使用params傳遞參數(shù),在this.$router.push() 方法中path不能和params一起使用,否則params將無(wú)效。需要用name來(lái)指定頁(yè)面。
B、以上方式參數(shù)不會(huì)顯示到瀏覽器的地址欄中,如果刷新一次頁(yè)面,就獲取不到參數(shù)了,改進(jìn)方式將第一部中的代碼改成如下:
{
path:'/home/three/:id/:name', // 子頁(yè)面3
name: 'three',
component:Three
}
編程式導(dǎo)航-query傳遞參數(shù)
(1)在src/router/index.js頁(yè)面加入如下代碼:
{
path:'/home/three', // 子頁(yè)面3
name: 'three',
component:Three
}
(2)在src/components/Three.vue頁(yè)面加入如下代碼:
<p>ID:{{ $route.query.id}}</p>
<p>名稱:{{ $route.query.name}}</p>
(3)在src/components/Home.vue中加入如下代碼:
// template
<button @click="toThreePage">頁(yè)面3-params傳參</button>
// script
methods: {
toThreePage() {
this.$router.push({path: '/home/three', query: {id: 1, name: 'zhangsan'}})
}
}
PS:動(dòng)態(tài)路由使用query傳遞參數(shù),會(huì)顯示到瀏覽器地址欄中,以上鏈接為
/home/three?id=1&name=zhangsan
命名路由-命名視圖-重定向-別名
命名路由
給一個(gè)路由命一個(gè)唯一的名稱,然后跳轉(zhuǎn)調(diào)用這個(gè)名稱即可。
(1)在src/router/index.js中加一個(gè)帶name的路由,代碼如下:
{
path: 'one', // 子頁(yè)面1
name: 'one', // 路由名稱-命名路由
component: One // 頁(yè)面組件
}
(2)在src/component/Home.vue頁(yè)面中調(diào)用,代碼如下:
// template跳轉(zhuǎn)調(diào)用
<router-link :to="{name: 'one'}">子頁(yè)面1</router-link>
// router.push函數(shù)跳轉(zhuǎn)調(diào)用
router.push({ name: 'user'}})
命名視圖
在同一個(gè)頁(yè)面展示多個(gè)視圖,如果不用嵌套,只能采用命名視圖來(lái)實(shí)現(xiàn)了,代碼如下:
(1)在src/router/index.js中,代碼如下:
import Vue from 'vue'
import Router from 'vue-router'
// 創(chuàng)建頁(yè)面組件
const Header = { template: '<div>Header</div>' }
const Left = { template: '<div>Left</div>' }
const Right = { template: '<div>Right</div>' }
Vue.use(Router)
export default new Router({
routes: [
{
path: '/', // 主頁(yè)路由
components: {
default: Header,
a: Left,
b: Right
}
}
]
})
(2)在src/App.vue中,代碼如下:
<template>
<div id="app">
<router-view />
<router-view name="a" class="left" />
<router-view name="b" class="right" />
</div>
</template>
<script>
export default {
name: 'App'
}
</script>
<style>
#app {
text-align: center;
color: #2c3e50;
width: 500px;
border: 1px solid red;
margin: 0 auto;
}
.left,.right{
float: left;
width:48%;
text-align: center;
border:1px solid red
}
</style>
PS:經(jīng)過(guò)實(shí)踐,命名視圖只能放在最頂級(jí)的頁(yè)面中,即第一步中的代碼不能放在其他頁(yè)面中。
重定向
重定向是通過(guò)route的配置中關(guān)鍵詞redirect來(lái)實(shí)現(xiàn)的,具體代碼如下:
(1)在src/router/index.js中,代碼如下:
export default new Router({
routes: [
{
path: '/', // 默認(rèn)頁(yè)面重定向到主頁(yè)
redirect: '/home' // 重定向
},
{
path: '/home', // 主頁(yè)路由
component: Home,
children:[ // 嵌套子路由
{
path:'/home/two/:id/:name', // 子頁(yè)面2
component:Two
},
{
path:'/home/three/:id/:name', // 子頁(yè)面3
name: 'three', // 路由名稱-命名路由
redirect: '/home/two/:id/:name' // 重定向-傳遞參數(shù)
},
]
}
]
})
(2)在src/components/Home.vue中,代碼如下:
<router-link to="/">首頁(yè)</router-link> |
<router-link to="/home/two/1/lisi">子頁(yè)面2</router-link> |
<router-link :to="{name: 'three', params: {id: 1, name: 'zhangsan'}}">子頁(yè)面3</router-link>
說(shuō)明1-不帶參數(shù)的重定向:
redirect: '/home' // 重定向-不帶參數(shù)
說(shuō)明2-帶參數(shù)的重定向:
redirect: '/home/two/:id/:name' // 重定向-傳遞參數(shù)
別名
重定向是通過(guò)route的配置中關(guān)鍵詞alias來(lái)實(shí)現(xiàn)的,具體代碼如下:
(1)在src/router/index.js中,代碼如下:
{
path:'/one', // 子頁(yè)面1
component:One,
alias: '/oneother'
}
(2)在src/components/Home.vue中,代碼如下:
<router-link to="/oneother">子頁(yè)面1</router-link>
說(shuō)明1:redirect和alias的區(qū)別
redirect:直接改變了url的值,把url變成了真實(shí)的path路徑。\ alias:url路徑?jīng)]有別改變,這種更友好,讓用戶知道自己訪問(wèn)的路徑,只是改變了 <router-view>中的內(nèi)容。
說(shuō)明2:
別名請(qǐng)不要用在path為’/’中,如下代碼的別名是不起作用的。
{
path: '/',
component: Hello,
alias:'/home'
}
過(guò)渡動(dòng)畫(huà)
代碼示例
(1)在<router-view>標(biāo)簽的外部添加<transition>標(biāo)簽,標(biāo)簽還需要一個(gè)name屬性,代碼如下:
<transition name="fade" mode="out-in">
<router-view />
</transition>
(2)加入CSS,一共4個(gè)CSS類名,四個(gè)類名與transition的name屬性有關(guān),比如name=”fade”,相應(yīng)的css如下:
/*頁(yè)面切換動(dòng)畫(huà)*/
/*進(jìn)入過(guò)渡的結(jié)束狀態(tài),元素被插入時(shí)就生效,在過(guò)渡過(guò)程完成后移除*/
.fade-enter-active {
transition: opacity .5s;
}
/*進(jìn)入過(guò)渡的開(kāi)始狀態(tài),元素被插入時(shí)生效,只應(yīng)用一幀后立刻刪除*/
.fade-enter {
opacity: 0;
}
/*離開(kāi)過(guò)渡的開(kāi)始狀態(tài),元素被刪除時(shí)觸發(fā),只應(yīng)用一幀后立刻刪除*/
.fade-leave {
opacity: 1;
}
/*離開(kāi)過(guò)渡的結(jié)束狀態(tài),元素被刪除時(shí)生效,離開(kāi)過(guò)渡完成后被刪除*/
.fade-leave-active {
opacity:0;
transition: opacity .5s;
}
過(guò)渡模式mode
in-out:新元素先進(jìn)入過(guò)渡,完成之后當(dāng)前元素過(guò)渡離開(kāi),默認(rèn)模式。 out-in:當(dāng)前元素先進(jìn)行過(guò)渡離開(kāi),離開(kāi)完成后新元素過(guò)渡進(jìn)入。
mode與404
mode模式
代碼示例:
export default new Router({
mode: 'history', //mode模式
routes: [...]
})
mode取值說(shuō)明:
(1)histroy:URL就像正常的 url,示例:http://localhost:8080/home
(2)hash:默認(rèn)值,會(huì)多一個(gè)“#”,示例:http://localhost:8080/#/home
404頁(yè)面設(shè)置
如果訪問(wèn)的路由不存在,或者用戶輸入錯(cuò)誤時(shí),會(huì)有一個(gè)404友好的提示頁(yè)面,配置如下:
(1)在/src/router/index.js中加入如下代碼:
// 404
{
path: '*',
component: () => import('@/components/404')
}
(2)在src/components/404.vue中編寫(xiě)如下代碼:
<template>
<div class="hello">
<h1>404 not found</h1>
</div>
</template>
<script>
export default {
data () {
return {
}
}
}
</script>
<style scoped>
</style>
路由鉤子
路由鉤子,即導(dǎo)航鉤子,其實(shí)就是路由攔截器,vue-router一共有三類:
全局鉤子:最常用 路由單獨(dú)鉤子 組件內(nèi)鉤子
全局鉤子
在src/router/index.js中使用,代碼如下:
// 定義路由配置
const router = new VueRouter({ ... })
// 全局路由攔截-進(jìn)入頁(yè)面前執(zhí)行
router.beforeEach((to, from, next) => {
// 這里可以加入全局登陸判斷
// 繼續(xù)執(zhí)行
next();
});
// 全局后置鉤子-常用于結(jié)束動(dòng)畫(huà)等
router.afterEach(() => {
//不接受next
});
export default router;
每個(gè)鉤子方法接收三個(gè)參數(shù):
to: Route : 即將要進(jìn)入的目標(biāo) [路由對(duì)象]
from: Route : 當(dāng)前導(dǎo)航正要離開(kāi)的路由
next: Function : 繼續(xù)執(zhí)行函數(shù)
next():繼續(xù)執(zhí)行 next(false):中斷當(dāng)前的導(dǎo)航。 next(‘/‘) 或 next({ path: ‘/‘ }):跳轉(zhuǎn)新頁(yè)面,常用于登陸失效跳轉(zhuǎn)登陸
路由單獨(dú)鉤子
使用:在路由配置中單獨(dú)加入鉤子,在src/router/index.js中使用,代碼如下:
{
path:'/home/one', // 子頁(yè)面1
component: One,
// 路由內(nèi)鉤子
beforeEnter: (to, from, next) => {
console.log('進(jìn)入前執(zhí)行');
next();
}
}
組件內(nèi)鉤子
使用:在路由組件內(nèi)定義鉤子函數(shù):
beforeRouteEnter:進(jìn)入頁(yè)面前調(diào)用 beforeRouteUpdate (2.2 新增):頁(yè)面路由改變時(shí)調(diào)用,一般需要帶參數(shù) beforeRouteLeave:離開(kāi)頁(yè)面調(diào)用
任意找一頁(yè)面,編寫(xiě)如下代碼:
<script>
export default {
name: 'Two',
data () {
return {
msg: 'Hi, I am Two Page!'
}
},
// 進(jìn)入頁(yè)面前調(diào)用
beforeRouteEnter(to, from, next) {
console.log('進(jìn)入enter路由鉤子')
next()
},
// 離開(kāi)頁(yè)面調(diào)用
beforeRouteLeave(to,from, next){
console.log('進(jìn)入leave路由鉤子')
next()
},
// 頁(yè)面路由改變時(shí)調(diào)用
beforeRouteUpdate(to, from, next) {
console.log('進(jìn)入update路由鉤子')
console.log(to.params.id)
next()
}
}
</script>
路由懶加載
路由正常模式:
// 1、先引入頁(yè)面組件
import Home from '@/components/Home'
// 2、使用組件
{
path: '/home',
component: Home
}
懶加載模式
大項(xiàng)目中,為了提高初始化頁(yè)面的效率,路由一般使用懶加載模式,一共三種實(shí)現(xiàn)方式。
(1)第一種寫(xiě)法:
component: (resolve) => require(['@/components/One'], resolve)
(2)第二種寫(xiě)法:
component: () => import('@/components/Two')
(3)第三種寫(xiě)法:
components: r => require.ensure([], () => r(require('@/components/Three')), 'group-home')
PS:
一般常用第二種簡(jiǎn)寫(xiě) 第三種中,’group-home’是把組件按組分塊打包, 可以將多個(gè)組件放入這個(gè)組中,在打包的時(shí)候Webpack會(huì)將相同 chunk 下的所有異步模塊打包到一個(gè)異步塊里面。
vue-cli
vue-cli是vue官方出品的快速構(gòu)建單頁(yè)應(yīng)用的腳手架,里面集成了webpack,npm,nodejs,babel,vue,vue-router等.
全局安裝vue-cli,命令行:
npm install vue-cli -g
初始化項(xiàng)目
在實(shí)際開(kāi)發(fā)中,一般都會(huì)使用webpack這個(gè)模板,命令使用如下:
vue init webpack my-vue-demo
運(yùn)行項(xiàng)目
npm run dev
以上命令為開(kāi)發(fā)模式下運(yùn)行項(xiàng)目
npm run build
以上命令為項(xiàng)目發(fā)布打包


main.js(入口文件)
// 引入vue框架
import Vue from 'vue'
// 引入根組件
import App from './App'
// 引入路由配置
import router from './router'
// 關(guān)閉生產(chǎn)模式下給出的提示
Vue.config.productionTip = false
// 定義實(shí)例
new Vue({
el: '#app',
router,
components: { App },
template: '<App/>'
})
router(路由配置)
// 引入vue框架
import Vue from 'vue'
// 引入vue-router路由依賴
import Router from 'vue-router'
// 引入頁(yè)面組件,命名為HelloWorld
import HelloWorld from '@/components/HelloWorld'
// 使用路由依賴
Vue.use(Router)
// 定義路由配置
export default new Router({
routes: [
{
path: '/',
name: 'HelloWorld',
component: HelloWorld
}
]
})
模板
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Vue入門(mén)之組件</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
<!-- template標(biāo)簽?zāi)0?nbsp;-->
<template id="demo2">
<h2 style="color:red">我是template標(biāo)簽?zāi)0?lt;/h2>
</template>
</div>
<!-- script標(biāo)簽?zāi)0?nbsp;-->
<script type="x-template" id="demo3">
<h2 style="color:red">我是script標(biāo)簽?zāi)0?lt;/h2>
</script>
<script type="text/javascript">
// 實(shí)例化
new Vue({
el: '#app',
data: {
message: 'hello'
},
// 選項(xiàng)模板
//template:`<h1 style="color:red">我是選項(xiàng)模板</h1>`
//template:'#demo2'
template:'#demo3'
});
</script>
</body>
</html>
組件注冊(cè)
(1)全局注冊(cè)
// script
Vue.component('button-counter', {
data: function () {
return {
count: 0
}
},
template: '<button v-on:click="count++">全局組件顯示: {{ count }}</button>'
});
new Vue({
el: '#app'
});
// html使用
<button-counter></button-counter>
(2)局部注冊(cè)
// script
new Vue({
el: '#app',
components:{
"button-inner":{
data: function() {
return {
inner: 0
}
},
template: '<button v-on:click="inner++">局部組件顯示: {{ inner }}</button>'
}
}
});
// html使用
<button-inner></button-inner>
自定義指令
vue中的自定義指令通過(guò)Vue.directive來(lái)實(shí)現(xiàn)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Vue入門(mén)之自定義指令</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
<div v-test="color">
{{num}}
</div>
</div>
<button onclick="unbindApp()">解綁</button>
<script type="text/javascript">
// 解綁
function unbindApp() {
app.$destroy();
}
// 自定義指令
Vue.directive("test",{
//1-被綁定
bind:function (el, binding, vnode) {
console.log("1-bind 被綁定");
console.log("el:",el);
console.log("binding:",binding);
console.log("vnode:",vnode);
el.style.color = binding.value;
},
//2-被插入
inserted:function (el, binding, vnode) {
console.log("2-inserted 被插入");
},
//3-更新
update:function (el, binding, vnode) {
console.log("3-update 更新");
},
//4-更新完成
componentUpdated:function (el, binding, vnode) {
console.log("4-componentUpdated 更新完成");
},
//5-解綁
unbind:function (el, binding, vnode) {
console.log("5-unbind 解綁");
}
});
var app = new Vue({
el:'#app',
data:{
num: 123,
color:'red'
}
})
</script>
</body>
</html>
參數(shù)說(shuō)明
el:指令所綁定的元素,可以用來(lái)直接操作DOM binding:一個(gè)對(duì)象,包含指令的很多信息 vnode::Vue編譯生成的虛擬節(jié)點(diǎn)
$on(在構(gòu)造器外部添加事件)
$on接收兩個(gè)參數(shù),第一個(gè)參數(shù)是調(diào)用時(shí)的事件名稱,第二個(gè)參數(shù)是一個(gè)匿名方法
app.$on('reduce',function(){
console.log('執(zhí)行了reduce()');
this.count--;
});
$once(執(zhí)行一次的事件)
app.$once('reduceOnce',function(){
console.log('只執(zhí)行一次的方法');
this.count--;
});
$off(關(guān)閉事件)
function off(){
console.log('關(guān)閉事件');
app.$off('reduce');
}
extends
擴(kuò)展:對(duì)構(gòu)造器進(jìn)行擴(kuò)展
// 擴(kuò)展
var extendObj ={
created: function(){
console.log("我是被擴(kuò)展出來(lái)的");
}
}
// 實(shí)例化vue
var app = new Vue({
// 掛載實(shí)例
el:'#app',
// 頁(yè)面數(shù)據(jù)初始化,字符,對(duì)象、數(shù)組
data:{
},
// 擴(kuò)展
extends: extendObj
})

??掘金文章
前端日??偨Y(jié) 一份不可多得的TypeScript系統(tǒng)入門(mén)整理 JS葵花寶典秘籍筆記,為你保駕護(hù)航金三銀四 TypeScript趁早學(xué)習(xí)提高職場(chǎng)競(jìng)爭(zhēng)力 前端模擬面試字?jǐn)?shù)過(guò)23477萬(wàn)內(nèi)容 JavaScript數(shù)據(jù)結(jié)構(gòu)之鏈表 | 技術(shù)點(diǎn)評(píng) JavaScript的數(shù)據(jù)結(jié)構(gòu)-集合 |技術(shù)點(diǎn)評(píng) 這是我的第一次JavaScript初級(jí)技巧 一個(gè)合格的初級(jí)前端工程師需要掌握的模塊筆記 【初級(jí)】個(gè)人分享Vue前端開(kāi)發(fā)教程筆記 localStorage和sessionStorage本地存儲(chǔ) HTML5中的拖放功能 挑戰(zhàn)前端知識(shí)點(diǎn)HTTP/ECMAScript 前端170面試題+答案學(xué)習(xí)整理(良心制作)
??關(guān)注+點(diǎn)贊+收藏+評(píng)論+轉(zhuǎn)發(fā)??
點(diǎn)贊、收藏和評(píng)論
我是Jeskson(達(dá)達(dá)前端),感謝各位人才的:點(diǎn)贊、收藏和評(píng)論,我們下期見(jiàn)!(如本文內(nèi)容有地方講解有誤,歡迎指出?謝謝,一起學(xué)習(xí)了)
我們下期見(jiàn)!
文章持續(xù)更新,可以微信搜一搜「 程序員哆啦A夢(mèng) 」第一時(shí)間閱讀,回復(fù)【資料】有我準(zhǔn)備的一線大廠資料,本文 https://www.1024bibi.com 已經(jīng)收錄
github收錄,歡迎Star:https://github.com/webVueBlog/WebFamily
