天天看點

vue-axios-vuex-全家桶axios狀态對象的擷取方法mutations-getters-actions異步傳遞參數module-子產品組vue-router頁面跳轉子路由-路由嵌套路由傳遞參數命名路由-命名視圖-重定向-别名過渡動畫mode與404路由鈎子路由懶加載vue-cli初始化項目模闆自定義指令

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

單向資料流

vue-axios-vuex-全家桶axios狀态對象的擷取方法mutations-getters-actions異步傳遞參數module-子產品組vue-router頁面跳轉子路由-路由嵌套路由傳遞參數命名路由-命名視圖-重定向-别名過渡動畫mode與404路由鈎子路由懶加載vue-cli初始化項目模闆自定義指令

示意圖說明:

  • 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-axios-vuex-全家桶axios狀态對象的擷取方法mutations-getters-actions異步傳遞參數module-子產品組vue-router頁面跳轉子路由-路由嵌套路由傳遞參數命名路由-命名視圖-重定向-别名過渡動畫mode與404路由鈎子路由懶加載vue-cli初始化項目模闆自定義指令

示意圖說明:

  1. Vue Components:Vue元件。HTML頁面上,負責接收使用者操作等互動行為,執行dispatch方法觸發對應action進行回應
  2. Dispatch:操作行為觸發方法,是唯一能執行action的方法
  3. Actions:操作行為處理子產品。負責處理Vue Components接收到的所有互動行為。包含同步/異步操作,支援多個同名方法,按照注冊的順序依次觸發。向背景API請求的操作就在這個子產品中進行,包括觸發其他action以及送出mutation的操作。該子產品提供了Promise的封裝,以支援action的鍊式觸發
  4. Commit:狀态改變送出操作方法。對mutation進行送出,是唯一能執行mutation的方法
  5. Mutations:狀态改變操作方法。是Vuex修改state的唯一推薦方法,其他修改方式在嚴格模式下将會報錯。該方法隻能進行同步操作,且方法名隻能全局唯一。操作之中會有一些hook暴露出來,以進行state的監控等
  6. State:頁面狀态管理容器對象。集中存儲Vue components中data對象的零散資料,全局唯一,以進行統一的狀态管理。頁面顯示所需的資料從該對象中進行讀取,利用Vue的細粒度資料響應機制來進行高效的狀态更新
  7. 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 :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一共有三類:

  1. 全局鈎子:最常用
  2. 路由單獨鈎子
  3. 元件内鈎子

全局鈎子

在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
           

以上指令為項目釋出打包

vue-axios-vuex-全家桶axios狀态對象的擷取方法mutations-getters-actions異步傳遞參數module-子產品組vue-router頁面跳轉子路由-路由嵌套路由傳遞參數命名路由-命名視圖-重定向-别名過渡動畫mode與404路由鈎子路由懶加載vue-cli初始化項目模闆自定義指令
vue-axios-vuex-全家桶axios狀态對象的擷取方法mutations-getters-actions異步傳遞參數module-子產品組vue-router頁面跳轉子路由-路由嵌套路由傳遞參數命名路由-命名視圖-重定向-别名過渡動畫mode與404路由鈎子路由懶加載vue-cli初始化項目模闆自定義指令

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
})
           
vue-axios-vuex-全家桶axios狀态對象的擷取方法mutations-getters-actions異步傳遞參數module-子產品組vue-router頁面跳轉子路由-路由嵌套路由傳遞參數命名路由-命名視圖-重定向-别名過渡動畫mode與404路由鈎子路由懶加載vue-cli初始化項目模闆自定義指令

點贊、收藏和評論

我是

Jeskson

(達達前端),感謝各位人才的:點贊、收藏和評論,我們下期見!(如本文内容有地方講解有誤,歡迎指出☞謝謝,一起學習了)

我們下期見!

github

收錄,歡迎

Star

:https://github.com/webVueBlog/WebFamily

繼續閱讀