Github來源: | 求星星 ✨ | 給個❤️關注,❤️點贊,❤️鼓勵一下作者
axios
Axios 是一個基于 promise 的 HTTP 庫,可以用在浏覽器和 node.js 中。簡單來說就是前端最火最簡單的一個http請求解決方案。
功能
- 從浏覽器中建立 XMLHttpRequests
- 從 node.js 建立 http 請求
- 支援 Promise API
- 攔截請求和響應
- 轉換請求資料和響應資料
- 取消請求
- 自動轉換 JSON 資料
- 用戶端支援防禦 XSRF
代碼封裝
工具類封裝
// 引入axios
import axios from 'axios';
// 建立axios執行個體
const httpService = axios.create({
// url字首-'https://some-domain.com/api/'
baseURL: process.env.BASE_API, // 需自定義
// 請求逾時時間
timeout: 3000 // 需自定義
});
// request攔截器
httpService.interceptors.request.use(
config => {
// 根據條件加入token-安全攜帶
if (true) { // 需自定義
// 讓每個請求攜帶token
config.headers['User-Token'] = '';
}
return config;
},
error => {
// 請求錯誤處理
Promise.reject(error);
}
)
// respone攔截器
httpService.interceptors.response.use(
response => {
// 統一處理狀态
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 = '錯誤請求';
break;
case 401:
error.message = '未授權,請重新登入';
break;
case 403:
error.message = '拒絕通路';
break;
case 404:
error.message = '請求錯誤,未找到該資源';
break;
case 405:
error.message = '請求方法未允許';
break;
case 408:
error.message = '請求逾時';
break;
case 500:
error.message = '伺服器端出錯';
break;
case 501:
error.message = '網絡未實作';
break;
case 502:
error.message = '網絡錯誤';
break;
case 503:
error.message = '服務不可用';
break;
case 504:
error.message = '網絡逾時';
break;
case 505:
error.message = 'http版本不支援該請求';
break;
default:
error.message = `未知錯誤${error.response.status}`;
}
} else {
error.message = "連接配接到伺服器失敗";
}
return Promise.reject(error);
}
)
/*網絡請求部分*/
/*
* get請求
* url:請求位址
* params:參數
* */
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請求
* url:請求位址
* params:參數
* */
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:請求位址
* params:參數
* */
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 = {}; // 參數
fetch.post(TMPURL + '/login/login', params);
vuex是什麼?
vuex是一個專為 Vue.js 應用程式開發的狀态管理模式。它采用集中式存儲管理應用的所有元件的狀态,并以相應的規則保證狀态以一種可預測的方式發生變化。chrome安裝調試工具 devtools extension
單向資料流
示意圖說明:
- State:驅動應用的資料源(單向資料流)
- View:以聲明方式将 state 映射到視圖(靜态顯示出來的資料源)
- Actions:處理使用者在view上面操作而導緻的狀态變化(資料源變化追蹤)
一個簡單的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解決的問題
- 多個視圖元件,包括父子元件,兄弟元件之間的狀态共享
- 不同視圖元件的行為需要變更同一個狀态
vuex使用場景
中大型單頁應用,需要考慮如何更好地在元件外部管理狀态,簡單應用不建議使用
vuex與全局變量的差別
- 響應式:vuex的狀态存儲是響應式的,當Vue元件從store中讀取狀态的時候,若store中的狀态發生變化,那麼相應的元件也會得到高效更新
- 不能直接改變store:不能直接改變store的變化,改變store中狀态的唯一途徑是commit mutation,友善于跟蹤每一個狀态的變化
vuex核心流程
示意圖說明:
- Vue Components:Vue元件。HTML頁面上,負責接收使用者操作等互動行為,執行dispatch方法觸發對應action進行回應
- Dispatch:操作行為觸發方法,是唯一能執行action的方法
- Actions:操作行為處理子產品。負責處理Vue Components接收到的所有互動行為。包含同步/異步操作,支援多個同名方法,按照注冊的順序依次觸發。向背景API請求的操作就在這個子產品中進行,包括觸發其他action以及送出mutation的操作。該子產品提供了Promise的封裝,以支援action的鍊式觸發
- Commit:狀态改變送出操作方法。對mutation進行送出,是唯一能執行mutation的方法
- Mutations:狀态改變操作方法。是Vuex修改state的唯一推薦方法,其他修改方式在嚴格模式下将會報錯。該方法隻能進行同步操作,且方法名隻能全局唯一。操作之中會有一些hook暴露出來,以進行state的監控等
- State:頁面狀态管理容器對象。集中存儲Vue components中data對象的零散資料,全局唯一,以進行統一的狀态管理。頁面顯示所需的資料從該對象中進行讀取,利用Vue的細粒度資料響應機制來進行高效的狀态更新
- Getters:state對象讀取方法。圖中沒有單獨列出該子產品,應該被包含在了render中,Vue Components通過該方法讀取全局state對象
總結說明:
Vue元件接收互動行為,調用dispatch方法觸發action相關處理,若頁面狀态需要改變,則調用commit方法送出mutation修改state,通過getters擷取到state新值,重新渲染Vue Components,界面随之更新
安裝
npm install vuex --save
簡單示例
(1)src/vuex/store.js中寫入以下代碼:
// 引入vue
import Vue from 'vue'
// 引入vuex
import Vuex from 'vuex'
// 使用vuex
Vue.use(Vuex)
// 1、state:建立初始化狀态
const state = {
// 放置初始狀态
count: 1
}
// 2、mutations:建立改變狀态的方法
const mutations = {
// 狀态變更函數-一般大寫
ADD (state, n) {
state.count += n;
}
}
// 3、getters:提供外部擷取state
const getters = {
count: function(state){
return state.count;
}
}
// 4、actions:建立驅動方法改變mutations
const actions ={
// 觸發mutations中相應的方法-一般小寫
add ({commit}, data) {
commit('ADD', data)
}
}
// 5、全部注入Store中
const store = new Vuex.Store({
state,
mutations,
getters,
actions
});
// 6、輸出store
export default store;
代碼說明:
- state - mutations - getters - actions - store,以上寫法基本固定。
- 小型項目用上面的簡單管理狀态即可。
(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頁面元件中代碼如下:
<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() {
//分發action中的add方法
this.$store.dispatch('add', 1);
}
}
}
</script>
<style scoped>
</style>
狀态對象的擷取方法
在元件的template中直接使用
<h2>{{ $store.state.count }}</h2>
在計算屬性computed中直接指派
// 方式1:直接擷取
computed: {
count() {
// this指的是main.js中的vue執行個體對象
return this.$store.state.count;
}
}
通過mapState的對象來指派
// 方式2:利用mapState
computed: mapState({
// es5寫法
count: function (state) {
return state.count;
},
// es6寫法
count: state => state.count
})
通過mapState的數組來指派
// 方式3:數組擷取
computed: mapState(['count'])
通過mapState的JSON來指派
// 方式4:JSON擷取
computed: mapState({
count: 'count'
})
mutations-getters-actions異步
mutations(修改狀态)
(1)template中直接使用$store.commit( )觸發
// template
<button @click="$store.commit('ADD')">+</button>
// src/vuex/store.js
const mutations = {
// 狀态變更函數
ADD (state) {
state.count++;
}
}
(2)利用mapMutations引入觸發
<template>
<div class="hello">
<h1>{{ msg }}</h1>
<h2>{{count}}</h2>
<!-- 3、、直接調用相應的方法 -->
<button @click="ADD">+</button>
</div>
</template>
<script>
// 1、引入mapMutations
import {mapState, mapMutations} from 'vuex'
export default {
data () {
return {
msg: 'Vuex test!'
}
},
// 通過mapState的JSON來指派
computed: mapState({
count: 'count'
}),
// 2、methods中加入mapMutations
methods: mapMutations([
'ADD'
])
}
</script>
<style scoped>
</style>
getters(擷取state和過濾)
(1)基本用法
// src/vuex/store.js
const getters = {
count: function(state){
// 傳回加上100
return state.count + 100;
}
}
(2)正常擷取值
computed: {
// 擷取getters
count(){
return this.$store.getters.count;
}
}
(3)mapGetters擷取值
// 1、引入mapMutations
import {mapState, mapMutations, mapGetters} from 'vuex'
// 2、使用
computed: {
// 擷取getters
...mapGetters(["count"])
}
actions(異步狀态修改)
actions和mutations功能基本一樣,不同點是,actions是異步的改變state狀态,而mutations是同步改變狀态。不過實際項目中一般都是通過actions改變mutations中的值。
(1)store.js中增加異步代碼
// src/vuex/store.js
const actions ={
// 觸發mutations中相應的方法
add ({commit}) {
// 增加異步
setTimeout(()=>{
commit('ADD')
},3000);
console.log('我比reduce提前執行');
}
}
(2)正常使用
// template
<button @click="add">+</button>
// script
methods: {
add() {
//分發action
this.$store.dispatch('add');
}
}
(3)mapActions的使用
// template
<button @click="add">+</button>
// script
// 引入mapActions
import {mapState, mapActions} from 'vuex'
// 使用mapActions
methods: {
...mapActions(['add'])
}
傳遞參數
隻需要在mutations和actions相應的地方加上參數,然後調用的時候傳入即可。
(1)src/vuex/store.js中
// actions中傳遞參數
const mutations = {
ADD (state, n) {
state.count += n;
}
}
// actions中傳遞參數
const actions ={
// 觸發mutations中相應的方法
add ({commit}, n) {
// 增加異步
setTimeout(()=>{
commit('ADD', n);
},3000);
console.log('我比reduce提前執行');
}
}
(2)頁面元件正常調用傳遞
// template
<button @click="add">+</button>
// script
methods: {
add() {
// 分發action
this.$store.dispatch('add', 99);
}
}
(3)頁面元件使用mapActions調用傳遞
// template
<button @click="add(99)">+</button>
// script
methods: {
...mapActions(['add'])
}
module-子產品組
當應用非常複雜,狀态非常多的時候,需要将store 分割成子產品(module)。每個子產品擁有自己的 state、mutation、action、getter、甚至是嵌套子子產品,從上至下進行同樣方式的分割。
大緻的結構
// 子產品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 的狀态
store.state.b // -> moduleB 的狀态
實際開發中建議把module分開編寫。
(1)src/vuex/module1.js
// 子產品1
const module1 = {
// 初始化狀态
state: {
module1: {
name: '子產品1'
}
},
// 編寫動作
mutations: {
CHANGE1 (state, data) {
state.module1 = data;
}
},
// 取值
getters: {
module1: function(state){
return state.module1;
}
},
// 建立驅動,可異步
actions: {
change1 ({commit}, data) {
commit('CHANGE1', data)
}
}
}
export default module1;
(2)src/vuex/module2.js
// 子產品1
const module2 = {
// 初始化狀态
state: {
module2: {
name: '子產品2'
}
},
// 編寫動作
mutations: {
CHANGE2 (state, data) {
state.module2 = data;
}
},
// 取值
getters: {
module2: function(state){
return state.module2;
}
},
// 建立驅動,可異步
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中命名要唯一,不然擷取值和改變值的時候會沖突,目前親測mapGetters隻能擷取對象。
vue-router
Vue Router 是 Vue.js 官方的路由管理器。它和 Vue.js 的核心深度內建,讓建構單頁面應用變得易如反掌。
包含的功能有:
- 嵌套的路由/視圖表
- 子產品化的、基于元件的路由配置
- 路由參數、查詢、通配符
- 基于 Vue.js 過渡系統的視圖過渡效果
- 細粒度的導航控制
- 帶有自動激活的 CSS class 的連結
- HTML5 曆史模式或 hash 模式,在 IE9 中自動降級
- 自定義的滾動條行為
安裝
使用指令安裝:
npm install vue-router --save
在src/router/index.js檔案中
// 引入vue架構
import Vue from 'vue'
// 引入vue-router路由依賴
import Router from 'vue-router'
// 引入頁面元件,命名為HelloWorld
import HelloWorld from '@/components/HelloWorld'
// Vue全局使用Router
Vue.use(Router)
// 定義路由配置
export default new Router({
routes: [ //配置路由,這裡是個數組
{ //每一個連結都是一個對象
path: '/', //連結路徑
name: 'HelloWorld', //路由名稱,
component: HelloWorld //對應的元件模闆
}
]
})
在系統入口檔案main.js中注入router,代碼如下:
// 引入vue架構
import Vue from 'vue'
// 引入根元件
import App from './App'
// 引入路由配置
import router from './router'
// 關閉生産模式下給出的提示
Vue.config.productionTip = false
// 定義執行個體
new Vue({
el: '#app',
router, // 注入架構中
components: { App },
template: '<App/>'
})
頁面跳轉
router-link标簽跳轉
在html标簽内使用router-link跳轉,相應于超連結a标簽,使用方式如下:
<router-link to="/">[顯示字段]</router-link>
to:導航路徑
使用示例如下:
<p>導航 :
<router-link to="/">首頁</router-link>
<router-link to="/hello">hello</router-link>
</p>
程式設計式導航-JS代碼内部跳轉
實際項目中,很多時候都是通過在JS代碼内部進行導航的跳轉,使用方式如下:
this.$router.push('/xxx')
具體的簡單用法:
(1)先編寫一個按鈕,在按鈕上綁定goHome( )方法。
<button @click="goHome">回到首頁</button>
(2)在
<script>
子產品裡加入goHome方法,并用
this.$router.push
(‘/’)導航到首頁
export default {
name: 'app',
methods: {
goHome(){
this.$router.push('/home');
}
}
}
其他常用方法
// 後退一步記錄,等同于 history.back()
this.$router.go(-1)
// 在浏覽器記錄中前進一步,等同于 history.forward()
this.$router.go(1)
子路由-路由嵌套
子路由,也叫路由嵌套,采用在children後跟路由數組來實作,數組裡和其他配置路由基本相同,需要配置path和component,然後在相應部分添加來展現子頁面資訊,相當于嵌入iframe。具體看下面的示例:
src/components/Home.vue(父頁面)
<template>
<div class="hello">
<h1>{{ msg }}</h1>
<!-- 添加子路由導航 -->
<p>導航 :
<router-link to="/home">首頁</router-link> |
<router-link to="/home/one">-子頁面1</router-link> |
<router-link to="/home/two">-子頁面2</router-link>
</p>
<!-- 子頁面展示部分 -->
<router-view/>
</div>
</template>
<script>
export default {
name: 'Home',
data () {
return {
msg: 'Home Page!'
}
}
}
</script>
<style scoped>
</style>
src/components/One.vue(子頁面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(子頁面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: '/', // 預設頁面重定向到首頁
redirect: '/home'
},
{
path: '/home', // 首頁路由
name: 'Home',
component: Home,
children:[ // 嵌套子路由
{
path:'one', // 子頁面1
component:One
},
{
path:'two', // 子頁面2
component:Two
},
]
}
]
})
路由傳遞參數
通過 <router-link>
标簽中的to傳參
<router-link>
基本文法:
<router-link :to="{name:xxx, params: {key:value}}">valueString</router-link>
PS:上面to前邊是帶冒号,後邊跟的是一個對象形勢的字元串
- name:在路由配置檔案中起的name值。叫做命名路由。
- params:要傳的參數,它是對象形式,在對象裡可以傳遞多個值。
具體執行個體如下:
(1)在src/components/Home.vue裡面導航中添加如下代碼:
<router-link :to="{name: 'one', params:{username:'test123'}}">子頁面1</router-link>
(2)在src/router/indes.js中添加如下代碼,重點是name:
{
path:'one', // 子頁面1
name: 'one', // 路由名稱-命名路由
component:One
}
(3)在src/components/One.vue裡面接受參數,代碼如下:
<h2>{{$route.params.username}}</h2>
url中傳遞參數
(1)在路由中以冒号傳遞,在src/router/index.js中加入如下代碼:
{
path:'/home/two/:id/:name', // 子頁面2
component:Two
},
(2)接受參數,在src/components/Two.vuez中加入如下代碼:
<p>ID:{{ $route.params.id}}</p>
<p>名稱:{{ $route.params.name}}</p>
(3)路由跳轉,在src/components/Home.vue中加入如下代碼:
<router-link to="/home/two/1/張三">子頁面2</router-link>
PS:to前沒有冒号為字元串路由,必須全部比對。
(4)如果路由參數需要有特定的規則,就需要加入正規表達式了,示例如下:
{
path:'/home/two/:id(\d+)/:name', // 子頁面2
component:Two
}
程式設計式導航-params傳遞參數
(1)在src/router/index.js頁面加入如下代碼:
{
path:'/home/three', // 子頁面3
name: 'three',
component:Three
}
(2)在src/components/Three.vue頁面加入如下代碼:
<p>ID:{{ $route.params.id}}</p>
<p>名稱:{{ $route.params.name}}</p>
(3)在src/components/Home.vue中加入如下代碼:
// template
<button @click="toThreePage">頁面3-params傳參</button>
// script
methods: {
toThreePage() {
this.$router.push({name: 'three', params: {id: 1, name: 'zhangsan'}})
}
}
說明:
A、動态路由使用params傳遞參數,在this.$router.push() 方法中path不能和params一起使用,否則params将無效。需要用name來指定頁面。
B、以上方式參數不會顯示到浏覽器的位址欄中,如果重新整理一次頁面,就擷取不到參數了,改進方式将第一部中的代碼改成如下:
{
path:'/home/three/:id/:name', // 子頁面3
name: 'three',
component:Three
}
程式設計式導航-query傳遞參數
(1)在src/router/index.js頁面加入如下代碼:
{
path:'/home/three', // 子頁面3
name: 'three',
component:Three
}
(2)在src/components/Three.vue頁面加入如下代碼:
<p>ID:{{ $route.query.id}}</p>
<p>名稱:{{ $route.query.name}}</p>
(3)在src/components/Home.vue中加入如下代碼:
// template
<button @click="toThreePage">頁面3-params傳參</button>
// script
methods: {
toThreePage() {
this.$router.push({path: '/home/three', query: {id: 1, name: 'zhangsan'}})
}
}
PS:動态路由使用query傳遞參數,會顯示到浏覽器位址欄中,以上連結為
/home/three?id=1&name=zhangsan
命名路由-命名視圖-重定向-别名
命名路由
給一個路由命一個唯一的名稱,然後跳轉調用這個名稱即可。
(1)在src/router/index.js中加一個帶name的路由,代碼如下:
{
path: 'one', // 子頁面1
name: 'one', // 路由名稱-命名路由
component: One // 頁面元件
}
(2)在src/component/Home.vue頁面中調用,代碼如下:
// template跳轉調用
<router-link :to="{name: 'one'}">子頁面1</router-link>
// router.push函數跳轉調用
router.push({ name: 'user'}})
命名視圖
在同一個頁面展示多個視圖,如果不用嵌套,隻能采用命名視圖來實作了,代碼如下:
(1)在src/router/index.js中,代碼如下:
import Vue from 'vue'
import Router from 'vue-router'
// 建立頁面元件
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: '/', // 首頁路由
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:經過實踐,命名視圖隻能放在最頂級的頁面中,即第一步中的代碼不能放在其他頁面中。
重定向
重定向是通過route的配置中關鍵詞redirect來實作的,具體代碼如下:
(1)在src/router/index.js中,代碼如下:
export default new Router({
routes: [
{
path: '/', // 預設頁面重定向到首頁
redirect: '/home' // 重定向
},
{
path: '/home', // 首頁路由
component: Home,
children:[ // 嵌套子路由
{
path:'/home/two/:id/:name', // 子頁面2
component:Two
},
{
path:'/home/three/:id/:name', // 子頁面3
name: 'three', // 路由名稱-命名路由
redirect: '/home/two/:id/:name' // 重定向-傳遞參數
},
]
}
]
})
(2)在src/components/Home.vue中,代碼如下:
<router-link to="/">首頁</router-link> |
<router-link to="/home/two/1/lisi">子頁面2</router-link> |
<router-link :to="{name: 'three', params: {id: 1, name: 'zhangsan'}}">子頁面3</router-link>
說明1-不帶參數的重定向:
redirect: '/home' // 重定向-不帶參數
說明2-帶參數的重定向:
redirect: '/home/two/:id/:name' // 重定向-傳遞參數
别名
重定向是通過route的配置中關鍵詞alias來實作的,具體代碼如下:
(1)在src/router/index.js中,代碼如下:
{
path:'/one', // 子頁面1
component:One,
alias: '/oneother'
}
(2)在src/components/Home.vue中,代碼如下:
<router-link to="/oneother">子頁面1</router-link>
說明1:redirect和alias的差別
- redirect:直接改變了url的值,把url變成了真實的path路徑。\
- alias:url路徑沒有别改變,這種更友好,讓使用者知道自己通路的路徑,隻是改變了
中的内容。<router-view>
說明2:
别名請不要用在path為’/’中,如下代碼的别名是不起作用的。
{
path: '/',
component: Hello,
alias:'/home'
}
過渡動畫
代碼示例
(1)在
<router-view>
标簽的外部添加
<transition>
标簽,标簽還需要一個name屬性,代碼如下:
<transition name="fade" mode="out-in">
<router-view />
</transition>
(2)加入CSS,一共4個CSS類名,四個類名與transition的name屬性有關,比如name=”fade”,相應的css如下:
/*頁面切換動畫*/
/*進入過渡的結束狀态,元素被插入時就生效,在過渡過程完成後移除*/
.fade-enter-active {
transition: opacity .5s;
}
/*進入過渡的開始狀态,元素被插入時生效,隻應用一幀後立刻删除*/
.fade-enter {
opacity: 0;
}
/*離開過渡的開始狀态,元素被删除時觸發,隻應用一幀後立刻删除*/
.fade-leave {
opacity: 1;
}
/*離開過渡的結束狀态,元素被删除時生效,離開過渡完成後被删除*/
.fade-leave-active {
opacity:0;
transition: opacity .5s;
}
過渡模式mode
- in-out:新元素先進入過渡,完成之後目前元素過渡離開,預設模式。
- out-in:目前元素先進行過渡離開,離開完成後新元素過渡進入。
mode與404
mode模式
代碼示例:
export default new Router({
mode: 'history', //mode模式
routes: [...]
})
mode取值說明:
(1)histroy:URL就像正常的 url,示例:http://localhost:8080/home
(2)hash:預設值,會多一個“#”,示例:http://localhost:8080/#/home
404頁面設定
如果通路的路由不存在,或者使用者輸入錯誤時,會有一個404友好的提示頁面,配置如下:
(1)在/src/router/index.js中加入如下代碼:
// 404
{
path: '*',
component: () => import('@/components/404')
}
(2)在src/components/404.vue中編寫如下代碼:
<template>
<div class="hello">
<h1>404 not found</h1>
</div>
</template>
<script>
export default {
data () {
return {
}
}
}
</script>
<style scoped>
</style>
路由鈎子
路由鈎子,即導航鈎子,其實就是路由攔截器,vue-router一共有三類:
- 全局鈎子:最常用
- 路由單獨鈎子
- 元件内鈎子
全局鈎子
在src/router/index.js中使用,代碼如下:
// 定義路由配置
const router = new VueRouter({ ... })
// 全局路由攔截-進入頁面前執行
router.beforeEach((to, from, next) => {
// 這裡可以加入全局登陸判斷
// 繼續執行
next();
});
// 全局後置鈎子-常用于結束動畫等
router.afterEach(() => {
//不接受next
});
export default router;
每個鈎子方法接收三個參數:
to: Route : 即将要進入的目标 [路由對象]
from: Route : 目前導航正要離開的路由
next: Function : 繼續執行函數
- next():繼續執行
- next(false):中斷目前的導航。
- next(‘/‘) 或 next({ path: ‘/‘ }):跳轉新頁面,常用于登陸失效跳轉登陸
路由單獨鈎子
使用:在路由配置中單獨加入鈎子,在src/router/index.js中使用,代碼如下:
{
path:'/home/one', // 子頁面1
component: One,
// 路由内鈎子
beforeEnter: (to, from, next) => {
console.log('進入前執行');
next();
}
}
元件内鈎子
使用:在路由元件内定義鈎子函數:
- beforeRouteEnter:進入頁面前調用
- beforeRouteUpdate (2.2 新增):頁面路由改變時調用,一般需要帶參數
- beforeRouteLeave:離開頁面調用
任意找一頁面,編寫如下代碼:
<script>
export default {
name: 'Two',
data () {
return {
msg: 'Hi, I am Two Page!'
}
},
// 進入頁面前調用
beforeRouteEnter(to, from, next) {
console.log('進入enter路由鈎子')
next()
},
// 離開頁面調用
beforeRouteLeave(to,from, next){
console.log('進入leave路由鈎子')
next()
},
// 頁面路由改變時調用
beforeRouteUpdate(to, from, next) {
console.log('進入update路由鈎子')
console.log(to.params.id)
next()
}
}
</script>
路由懶加載
路由正常模式:
// 1、先引入頁面元件
import Home from '@/components/Home'
// 2、使用元件
{
path: '/home',
component: Home
}
懶加載模式
大項目中,為了提高初始化頁面的效率,路由一般使用懶加載模式,一共三種實作方式。
(1)第一種寫法:
component: (resolve) => require(['@/components/One'], resolve)
(2)第二種寫法:
component: () => import('@/components/Two')
(3)第三種寫法:
components: r => require.ensure([], () => r(require('@/components/Three')), 'group-home')
PS:
- 一般常用第二種簡寫
- 第三種中,’group-home’是把元件按組分塊打包, 可以将多個元件放入這個組中,在打包的時候Webpack會将相同 chunk 下的所有異步子產品打包到一個異步塊裡面。
vue-cli
vue-cli是vue官方出品的快速建構單頁應用的腳手架,裡面內建了webpack,npm,nodejs,babel,vue,vue-router等.
全局安裝vue-cli,指令行:
npm install vue-cli -g
初始化項目
在實際開發中,一般都會使用webpack這個模闆,指令使用如下:
vue init webpack my-vue-demo
運作項目
npm run dev
以上指令為開發模式下運作項目
npm run build
以上指令為項目釋出打包
main.js(入口檔案)
// 引入vue架構
import Vue from 'vue'
// 引入根元件
import App from './App'
// 引入路由配置
import router from './router'
// 關閉生産模式下給出的提示
Vue.config.productionTip = false
// 定義執行個體
new Vue({
el: '#app',
router,
components: { App },
template: '<App/>'
})
router(路由配置)
// 引入vue架構
import Vue from 'vue'
// 引入vue-router路由依賴
import Router from 'vue-router'
// 引入頁面元件,命名為HelloWorld
import HelloWorld from '@/components/HelloWorld'
// 使用路由依賴
Vue.use(Router)
// 定義路由配置
export default new Router({
routes: [
{
path: '/',
name: 'HelloWorld',
component: HelloWorld
}
]
})
模闆
<!DOCTYPE html>
<html >
<head>
<meta charset="UTF-8">
<title>Vue入門之元件</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
<!-- template标簽模闆 -->
<template id="demo2">
<h2 style="color:red">我是template标簽模闆</h2>
</template>
</div>
<!-- script标簽模闆 -->
<script type="x-template" id="demo3">
<h2 style="color:red">我是script标簽模闆</h2>
</script>
<script type="text/javascript">
// 執行個體化
new Vue({
el: '#app',
data: {
message: 'hello'
},
// 選項模闆
//template:`<h1 style="color:red">我是選項模闆</h1>`
//template:'#demo2'
template:'#demo3'
});
</script>
</body>
</html>
元件注冊
(1)全局注冊
// 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)局部注冊
// 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中的自定義指令通過Vue.directive來實作
<!DOCTYPE html>
<html >
<head>
<meta charset="UTF-8">
<title>Vue入門之自定義指令</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>
參數說明
- el:指令所綁定的元素,可以用來直接操作DOM
- binding: 一個對象,包含指令的很多資訊
- vnode::Vue編譯生成的虛拟節點
$on(在構造器外部添加事件)
$on接收兩個參數,第一個參數是調用時的事件名稱,第二個參數是一個匿名方法
app.$on('reduce',function(){
console.log('執行了reduce()');
this.count--;
});
$once(執行一次的事件)
app.$once('reduceOnce',function(){
console.log('隻執行一次的方法');
this.count--;
});
$off(關閉事件)
function off(){
console.log('關閉事件');
app.$off('reduce');
}
extends
擴充:對構造器進行擴充
// 擴充
var extendObj ={
created: function(){
console.log("我是被擴充出來的");
}
}
// 執行個體化vue
var app = new Vue({
// 挂載執行個體
el:'#app',
// 頁面資料初始化,字元,對象、數組
data:{
},
// 擴充
extends: extendObj
})
點贊、收藏和評論
我是
Jeskson
(達達前端),感謝各位人才的:點贊、收藏和評論,我們下期見!(如本文内容有地方講解有誤,歡迎指出☞謝謝,一起學習了)
我們下期見!
收錄,歡迎
github
:https://github.com/webVueBlog/WebFamily
Star