Vue2 基礎知識

  • JavaScript 表達式(Expression):

    1. 表達式是可以計算并返回一個值的任何合法的 JavaScript 結構。
    2. 它們可以是一個簡單的字面量(例如數(shù)字、字符串或布爾值),也可以是復雜的組合,包括算術運算符連接的操作數(shù)、函數(shù)調用、屬性訪問、對象和數(shù)組字面量等。
    3. 表達式總是會生成一個值,這個值可以被賦給變量、作為參數(shù)傳遞給函數(shù),或者直接參與進一步的計算。
  • JavaScript 代碼(Code):

    1. JavaScript 代碼通常指的是一個或多個 JavaScript 語句的集合,它們共同構成了一段可執(zhí)行邏輯的單元。
    2. 語句不一定要返回值,而是用來描述一系列操作,這些操作可以改變程序的狀態(tài),控制流程(如條件語句、循環(huán)語句等)。

簡單來說,一個表達式會產生一個值,而一個代碼塊則會執(zhí)行一系列操作。

MVVM

  • M: 模型(Model) : 對應 data 中的數(shù)據
  • V: 視圖(View) : 模板
  • VM: 視圖模型(ViewModel) : Vue 實例對象

Object.defineProperty()

  • 數(shù)據代理:通過一個對象代理對另一個對象中屬性的操作(讀/寫)
  • 數(shù)據代理的好處:更加方便的操作數(shù)據
let per = {
  name: "張三",
  sex: "男",
};

Object.defineProperty(per, "age", {
  value: 500,
  enumerable: true, // 控制屬性是否可以枚舉,默認值是 false
  writable: true, // 控制屬性是否可以被修改,默認值是 false,
  configurable: true, // 控制屬性是否可以被刪除,默認值是 false

  get() {}, // 用來獲取屬性值的函數(shù)(當有人讀取屬性時,get 函數(shù)(getter)就會被調用,且返回值
  set() {}, // 用來設置屬性值的函數(shù)(當有人修改屬性時,set 函數(shù)(setter)就會被調用,
});

Vue 中的數(shù)據代理

  • 基本原理:通過 Object.defineProperty()把 data 對象中的所有屬性添加到 vm 上

    • 為每一個添加到 vm 上的屬性,都指定一個 getter/setter

    • 在 getter/setter 中去操作(讀/寫) data 中對應的屬性

Vue 中的事件處理

  • @click="show" === v-on:click="show($event)"

  • 事件修飾符:

    1. .stop:阻止事件冒泡
    2. .prevent:阻止默認事件
    3. .once:事件只觸發(fā)一次
    4. .capture:使用事件捕獲模式
    5. .self:只有 event.target 是當前操作的元素時才觸發(fā)事件
    6. .passive:事件的默認行為立即執(zhí)行,無需等待事件回調執(zhí)行完畢
  • 按鍵別名:(@keyup.XXX)

    1. 回車 enter
    2. 刪除 delete(捕獲“刪除”和“退格”鍵)
    3. 退出 esc
    4. 空格 space
    5. 換行 tab(需配合@keydown 使用)
    6. 上 up
    7. 下 down
    8. 左 left
    9. 右 right

計算屬性 computed

  • 定義:通過已有的屬性進行計算得到的新的屬性
  • 優(yōu)勢:與 methods 實現(xiàn)相比,內部有緩存機制(復用),效率更高,調試方便
    • data 里面放的是屬性
    • computed 里面放的是計算屬性
computed: {
  fullName {
    // 當fullName屬性被讀取時,get() 方法會被調用,且返回值就作為 fullName 的值
    // 初次獲取fullName和所依賴項發(fā)生變化時,都會調用get(依賴項指的是計算屬性中所有用到的屬性)
    get(){
        return this.firstName + this.lastName;
    },
     // 當fullName被修改時調用
    set(value) {
        const arr = value.split(' ')
        this.firstName = arr[0]
        this.lastName = arr[1]
    }
  },
    // 大多數(shù)情況下計算屬性是不需要修改的,可以簡寫為
  fullName() {
    return this.firstName + this.lastName;
  }
}

監(jiān)視屬性 watch

  • 當被監(jiān)視的屬性變化時,回調函數(shù)自動調用,進行相關操作

    • 注意
      1. 監(jiān)視的屬性必須存在(必須在 data 里存在),才能進行監(jiān)視
  • 深度監(jiān)視

watch: {
  isHot: {
    deep: true, // 配置deep: true可以檢測對象內部值的改變
    immediate: true, // 初始化時讓handler調用一下
    handler(newValue, oldValue) {
        onsole.log('isHot被修改了', newValue, oldValue)
      }
  },
  // 如果不需要其他配置項的,可以簡寫成
  isHot(newValue, oldValue) {
    console.log('isHot被修改了', newValue, oldValue)
  }

}

watch 和 computed 的區(qū)別

  1. computed 存在緩存機制,當他依賴項沒有變化時,不會重新執(zhí)行。而 watch 每次都會執(zhí)行。
  2. computed 只能是執(zhí)行同步代碼。而 watch 支持異步(也就是可以用 setTimeout)。
  3. computed 有返回值。而 watch 沒有返回值,需要手動處理數(shù)據。

key 的作用

  • key 是給每一個虛擬 DOM 增加的唯一標識,可以根據 key 更準確、更快的找到對應的節(jié)點

VUE 檢測數(shù)據變化的原理

  • VUE 是如何監(jiān)測對象里面數(shù)據改變的?

    1. 遍歷對象的屬性
    2. 給屬性添加 getter 和 setter
    3. 遇到對象嵌套問題,進行遞歸
  • Vue.set & this.$set

    • 用于為對象添加響應式屬性
    • 語法:Vue.set( target, propertyName/index, value )
      • target:要更改的數(shù)據源(可以是對象或者數(shù)組)
      • propertyName/index:要更改的具體數(shù)據
      • value:重新賦的值
      • 注意:Vue.set 只能給 data 里的對象追加屬性而不能給 data 追加
  • VUE 是如何監(jiān)測數(shù)組里面數(shù)據改變的?

    1. 通過調用數(shù)組的一些方法(push, pop, shift, unshift, splice, sort, reverse)來監(jiān)聽數(shù)組變化,VUE 將這些方法進行了包裹
      注意:不能使用數(shù)組索引直接修改

v-cloak

  • 用于解決網速慢時 vue.js 未能加載出來,頁面出現(xiàn){{xxx}}的問題,配合 css 來提升用戶體驗
[v-cloak]{
  display: none;
}

<div v-cloak>{{name}}</div>

VUE 自定義指令

  • 需求:定義一個 v-big 指令,和 v-text 功能類似,但會把綁定的數(shù)值放大 10 倍

<span v-big="count"></span>

data: {
  count: 1
}

directives: {
  // big函數(shù)會在一開始和所綁定的數(shù)據發(fā)生改變時調用
  big(element, binding) {
    element.innerText = binding.value * 10
  }
}

生命周期

  • 掛載流程

    1. beforeCreate:無法拿到 data 中的數(shù)據和 methods 中的方法

    2. created:可以拿到 data 中的數(shù)據和 methods 中的方法

      這個時候 Vue 開始解析模版生成虛擬 DOM,但是頁面還不能顯示解析好的內容

    3. beforeMount:頁面呈現(xiàn)的是未經編譯的 DOM,此時對 DOM 的操作最終不生效

      這個時候內存中的虛擬 DOM 會轉為真實 DOM 插入頁面,所以在 beforeMount 操作的 DOM 就不奏效了

    4. mounted:頁面呈現(xiàn)的是經過編譯的 DOM,此時可以對 DOM 進行操作(一般在此時進行開啟定時器、發(fā)送網絡請求、訂閱消息、綁定事件等操作)

  • 更新流程

    1. beforeUpdate:操作事件改變數(shù)據后,數(shù)據已更新但頁面尚未與數(shù)據同步
    2. updated:頁面和數(shù)據同步,保持最新
  • 銷毀流程

    1. beforeDestroy:此時可以拿到 data 中的數(shù)據和 methods 中的方法,但是對數(shù)據的修改不再觸發(fā)更新(一般在此時解綁事件監(jiān)聽器,清理定時器等)

      注意:銷毀后自定義事件會失效,但是原生 DOM 事件依然有效

    2. destroyed:所有指令都被解綁,所有的事件監(jiān)聽器被移除,所有的子實例也都被銷毀。

VUE 組件命名規(guī)范

  • 一個單詞組成

    1. 首字母小寫:header
    2. 首字母大寫:Header
  • 多個單詞組成

    1. kebab-case 命名:goods-list
    2. CamelCase 命名:GoodsList

VueComponent

  1. 組件本質是一個名為 VueComponent 的構造函數(shù),且不是程序員定義的,是 Vue.extend 生成的
  2. 當在代碼中寫入<component-name/>的時候,Vue 會創(chuàng)建 component-name 組件的實例對象,即執(zhí)行 new VueComponent(options)
    注意:每次使用 Vue.extend 返回的都是全新的 VueComponent
  3. 組件配置中this指的是 VueComponent 實例對象,new Vue(options)中this指的是 Vue 實例對象

腳手架

  • 安裝腳手架
npm install -g @vue/cli
  • 創(chuàng)建項目
vue create my-project
  • 項目目錄
├── node_modules
├── public
│   ├── favicon.ico: 頁簽圖標
│   └── index.html: 主頁面
├── src
│   ├── assets: 存放靜態(tài)資源
│   │   └── logo.png
│   │── main.js: 入口文件
│   │── App.vue: 匯總所有組件
│   │── components: 存放組件
│   │   └── HelloWorld.vue
│   └── views: 存放頁面
│       └── Home.vue
├── .gitignore: git 版本管制忽略的配置
├── babel.config.js: babel 的配置文件
├── package.json: 應用包配置文件
├── package-lock.json: 包版本控制文件
├── README.md: 應用描述文件
└── vue.config.js: vue 腳手架的配置文件

ref 屬性

  • 應用在 HTML 標簽上獲取的是真實 DOM 元素,應用在組件標簽上是組件實例對象(vc VueComponent)

props

  • 功能:讓組件接收外部傳過來的數(shù)據
export default {
  name: "GoodsList",
  data() {
    return {};
  },
  // 完整方式
  props: {
    name: {
      type: String,
      required: true,
    },
    price: {
      type: Number,
      default: 1000,
    },
  },
};

mixin

  • 功能:可以把多個組件共用的配置提取成一個混入對象
// 定義
export const mixin = {
  mounted() {
    console.log("mixin 的 mounted 被調用了");
  },
};
// 使用
import { mixin } from "../mixin";

export default {
  name: "GoodsList",
  data() {
    return {};
  },
  mixins: [mixin],
};

插件

  • 功能:用于增強 Vue
  • 本質:包含 install 方法的一個對象,install 的第一個參數(shù)是 Vue,第二個以后的參數(shù)是插件使用者傳遞的數(shù)據
// 定義
export default {
  install(Vue, options) {
    // 1. 添加全局過濾器
    Vue.filter(....)
    // 2. 添加全局指令
    Vue.directive(....)
    // 3. 配置全局混入(合)
    Vue.mixin(....)
    // 4. 添加實例方法
    Vue.prototype.$myMethod = function() {...}
    Vue.prototype.$myProperty = xxxx
  },
}
// 使用
Vue.use();

組件通信

  • 父傳子

    • 利用 props
    1. 父組件將要傳遞的值或者方法通過標簽屬性形式傳遞給子組件
    2. 子組件利用 props 接收父組件傳遞過來的值或者方法并使用
      注意:props 是一個數(shù)組 props:[]
  • 子傳父

    • 利用 props
    1. 父組件通過標簽屬性形式傳遞一個函數(shù)給子組件
    2. 子組件通過該函數(shù)將數(shù)據傳遞給父組件
    • 利用 $emit
    1. 父組件通過標簽屬性形式給子組件綁定一個自定義事件
    2. 子組件通過 $emit 觸發(fā)該事件,并將數(shù)據傳遞給父組件
    // 父組件
    // 通過父組件給子組件綁定一個自定義事件
    <ChildComponent @getData="getChildData"></ChildComponent>
    
    methods: {
      getChildData(data) {
        console.log(data);
      }
    }
    
    // 子組件
    <button @click="sendData">點擊</button>
    
    methods: {
      sendData() {
        this.$emit("getData", data);
    }},
    beforeDestroy(){
      // 通過$off解綁自定義事件
      // 解綁一個
      this.$off("getData");
      // 解綁多個
      this.$off(["getData",...]);
      // 全部解綁
      this.$off();
    }
    
    • 利用全局事件總線

自定義事件

  • 一種組件間通信的方式,適用于:子組件 ===> 父組件
  • 具體實現(xiàn):見標題為 《組件通信》 的內容
  • :如果在組件中使用原生(如 @click)事件,需要寫成@click.native

全局事件總線

  • 一種組件間通信的方式,適用于:任意組件間通信
  1. 在 new Vue 的時候,通過beforeCreate生命周期在 Vue 的 prototype 上綁定一個屬性(隨便任何名字),值為 this
new Vue({
  // ...
  beforeCreate() {
    Vue.prototype.$bus = this; // 安裝全局事件總線
  },
});
  1. 在 A 組件中通過this.$bus.$on來接收數(shù)據
mounted: {
  this.$bus.$on("getData", (data) => {
    console.log(data);
  });
}
beforeDestroy() {
  this.$bus.$off("getData"); // 解綁getData事件
}
  1. 在 B 組件中通過this.$bus.$emit來發(fā)送數(shù)據
<button @click="sendMsg">發(fā)送信息</button>

data(){
  return {
    msg: "Hello World"
  }
},
methods: {
  sendMsg() {
    this.$bus.$emit("getData", this.msg);
  },
}

消息訂閱與發(fā)布

  • 一種組件間通信的方式,適用于:任意組件間通信
  1. 安裝pubsub-js
npm install pubsub-js
  1. 引入PubSub
import PubSub from 'pubsub-js'
  1. 使用
    注意:接收數(shù)據和發(fā)送數(shù)據的事件名稱必須一致
// 在傳遞數(shù)據的組件中,通過`PubSub.publish`來發(fā)送數(shù)據
PubSub.publish("getMsg", { name: "curry" });
// 在接收數(shù)據的組件中,通過`PubSub.subscribe`來接收數(shù)據(一般是當該組件加載完之后就要先注冊一下接收數(shù)據的事件,所以一般寫在`mounted`生命周期中)
mounted() {
 this.pubId = PubSub.subscribe("getMsg", (msg, data) => {
   console.log(msg, data, "接收來的數(shù)據");
 });
},
beforeDestroy() {
 PubSub.unsubscribe(this.pubId); // 組件銷毀前,一定要取消訂閱
}

$nextTick

  • 語法:this.$nextTick(回調函數(shù))

  • 官方解釋:在下一次 DOM 更新結束后執(zhí)行指定的回調函數(shù)

  • 自己解釋:當你修改了數(shù)據之后,Vue 幫你操作完 DOM 之后,把真實的 DOM 放入頁面了,Vue 再幫你調用這個函數(shù)

axios

  • 作用:發(fā)送 ajax 請求

  • 安裝

npm install axios
  • 引入
import axios from 'axios'
  • vue.config.js 配置代理
module.exports = {
  // 方式1 配置單個代理
  devServer: {
    proxy: "http://localhost:3000",
  },
  // 方式2 配置多個代理
  devServer: {
    proxy: {
      "/api": {
        // 前綴 緊跟在端口號后面
        target: "http://localhost:3000", // 代理服務器地址
        pathRewrite: {
          "^/api": "", // 包含api的替換為空
        },
        ws: true, // 是否啟用websockets
        changeOrigin: true, // 用戶控制請求頭中的host值
      },
      "/foo": {
        target: "...",
      },
    },
  },
};

插槽 slot

  • 作用:讓父組件可以向子組件指定位置插入 html 結構,也是一種組件間通信的方式,適用于父組件 ===> 子組件(傳遞的是 html 結構)

  • 默認插槽

    1. 在父組件中傳入內容
    <Category title="游戲">
      <img src="https://..." />
    </Category>
    
    1. 在子組件中定義
    <slot> 我是默認內容,當沒有傳入內容的時候,就展示我 </slot>
    
  • 具名插槽

  1. 在父組件中傳入內容
<Category title="游戲">
  <img src="https://..." slot="img" />
  <a href="#" slot="link">點擊去詳情</a>
</Category>
  1. 在子組件中定義
<div>
  <slot name="img"></slot>
  <slot name="link"></slot>
</div>
  • 作用域插槽
  • 注:作用域插槽中子組件可以向父組件傳數(shù)據,也就是 HTML 結構是父組件來規(guī)定,數(shù)據由子組件來提供(子組件傳給父組件的)
  1. 子組件
<slot :dataSource="games"></slot>

export default {
  data(){
    return {
      games: ['紅色警戒', '穿越火線', '勁舞團', '超級瑪麗']
    }
  }
}
  1. 父組件
<template scope="dataSource" || scope="{games}">
  <ul>
    <li v-for="item in dataSource.games" :key="item">{{item}}</li>
  </ul>
</template>

Vuex

  • 概念:在 Vue 中實現(xiàn)集中式狀態(tài)(數(shù)據)管理的一個 Vue 插件,對 vue 應用中多個組件共享狀態(tài)進行集中式的管理
    注意 vue2 中只能使用 vuex 的 3 版本
    注意 vue3 中只能使用 vuex 的 4 版本

  • 安裝及使用

  1. npm install vuex

  2. 在 src 下創(chuàng)建 store 文件夾,創(chuàng)建 index.js 文件

  3. index.js 的內容

    import Vue from "vue";
    import Vuex from "vuex";
    Vue.use(Vuex);
    
    // 準備actions - 用于響應組件中的動作
    const actions = {
      increment(context, value) {
        console.log("+++", context, value);
        context.commit("INCREMENT", value);
      },
    };
    
    // 準備mutations - 用于操作數(shù)據(state)
    const mutations = {
      INCREMENT(state, value) {
        state.count += value;
      },
    };
    
    // 準備state - 用于存儲數(shù)據
    const state = {
      count: 0,
    };
    
    //準備getters - 用于將state中的數(shù)據進行加工
    const getters = {
      powerCouunt(state) {
        return state.count * state.count;
      },
    };
    
    // 創(chuàng)建store
    const store = new Vuex.Store({
      actions,
      mutations,
      getters,
      state,
    });
    
    export default store;
    
  4. 在 main.js 中創(chuàng)建 vue 實例時傳入 store 對象

    import store from "./store";
    
  5. 在組件中觸發(fā)

    methods: {
      handleClick() {
        this.$store.dispatch("increment", 5);
      }
    }
    
  6. 在組件中獲取

    <h1>{{ $store.state.count }}</h1>
    <h1>{{ $store.getters.powerCouunt }}</h1>
    
  7. mapState

    import { mapState } from "vuex";
    
    computed: {
     // 寫法一:借助mapState生成計算屬性,從state中讀取數(shù)據。(對象寫法)
      ...mapState({shu:'count',...})
    
     // 寫法二:借助mapState生成計算屬性,從state中讀取數(shù)據。(數(shù)組寫法)
      ...mapState(['count'])
    }
    
    <h1>{{shu}}</h1>  // 寫法一
    <h1>{{count}}</h1>  // 寫法二
    
  8. mapGetters

  import { mapGetters } from "vuex";

  computed: {
   // 寫法一:借助mapGetters生成計算屬性,從getters中讀取數(shù)據。(對象寫法)
    ...mapGetters({zong:'powerCouunt'})

   // 寫法二:借助mapGetters生成計算屬性,從getters中讀取數(shù)據。(數(shù)組寫法)
    ...mapGetters(['powerCouunt'])
  }

  <h2>{{zong}}</h2>  // 寫法一
  <h2>{{powerCouunt}}</h2>  // 寫法二
  1. mapMutations
  import { mapMutations } from "vuex";

  methods: {
    // 借助mapMutations生成對應的方法,方法中會調用commit去聯(lián)系mutations(推薦:對象寫法)
    ...mapMutations({increment:'INCREMENT'})
  }

  <button @click="increment(3)"> + 3 </button>
  1. mapActions
  import { mapActions } from "vuex";
  // 借助mapActions生成對應的方法,方法中會調用dispatch去聯(lián)系actions(推薦:數(shù)組寫法)
  methods: {
   ...mapActions(['increment'])
  }

  <button @click="increment(3)"> + 3 </button>
  1. namespace
  // 第一步: 在store下的index.js中根據模塊創(chuàng)建對象
  const countAbout = {
    namespaced: true, // 開啟命名空間
    state: () => ({ ... }),
    mutations: { ... },
    actions: { ... },
    getters: { ... }
  }

  // 第二步: 將創(chuàng)建好的模塊導出
  const store = new Vuex.Store({
    modules: {
      countAbout: countAbout,
      ...
    }
  })


  // 第三步: 在組件中使用
  <h1>{{count}}</h1>

  import { mapState } from 'vuex'
  computed: {
    // 根據namespace找對它對應的state中的數(shù)據
    // 因為數(shù)據有多個,所以用數(shù)組形式
    // 如果有多個命名空間,需要多寫幾個mapState
    ...mapState('countAbout',['count'])
    // ...
  }

  // 第四步: 跟命名空間相對應的mapActions、mapMutations...都需要修改
   ...mapMutations('countAbout',{increment:'INCREMENT',...})
   ...mapState('countAbout',{count:'count',...})
  1. 總結
    11.1. 用戶點擊按鈕,調用 store.dispatch() 方法
    11.2. store.dispatch() 方法將 action 對象發(fā)送給 store
    11.3. store 中的 action 調用對應的 mutations 中的方法,來操作 store 中的 state
    11.4. mutations 中的方法完成并重新渲染頁面

    注意:
    11.5. 如果點擊按鈕后的操作沒有任何邏輯,可以直接通過 commit 調用 mutations 中的方法來修改 state
    11.6. 如果當前一個 action 的操作和邏輯過多,可以通過調用 context.dispatch()繼續(xù)執(zhí)行其他 action
    不成文的規(guī)定:
    11.7. actions 中的方法和 mutations 中的方法名最好相同,但是 mutations 中的方法名最好寫成大寫

路由

注意 vue2 中只能使用 vue-router3 版本
注意 vue3 中只能使用 vue-router4 版本

  • 安裝及使用
  1. npm install vue-router@3
  2. 在 src 下創(chuàng)建 router 文件夾,創(chuàng)建 index.js 文件
  3. index.js 的內容
import VueRouter from "vue-router";

import Home from "../pages/Home";
import About from "../pages/About";
import Message from "../pages/Message";

const router = new VueRouter({
  routes: [
    {
      path: "/home",
      component: Home,
    },
    {
      path: "/about",
      component: About,
      children: [
        {
          path: "message", // 路由嵌套時,子級路由中的path不要加斜線( / )
          component: Message,
        },
      ],
    },
  ],
});
export default router;
  1. 在 main.js 中引入并使用自己編寫的 router 文件和 VueRouter 插件
import Vue from "vue";
import App from "./App.vue";
import VueRouter from "vue-router";
import router from "./router";

Vue.use(VueRouter);

new Vue({
  render: (h) => h(App),
  router,
}).$mount("#app");
  1. 導航組件用<router-link to="home">首頁</router-link>標簽包裹,路由組件用<router-view></router-view>標簽來展示內容(類似于 slot)

  2. 路由組件傳參
    6.1 query 傳參(好處:不會影響 router 里面的 path)

    <router-link to="/about/message?id=3"> message </router-link>
    
    mounted() {
     console.log(this.$route); // 通過$route獲取傳參
    },
    

    6.2 命名路由(作用:路由嵌套層數(shù)過多時,簡化路由的路徑)

    // router/index.js
    const router = new VueRouter({
      routes: [
        {
          path: "/about",
          component: About,
          children: [
            {
              name: "message", // 命名路由
              path: "message", // 路由嵌套時,子級路由中的path不要加斜線( / )
              component: Message,
            },
          ],
        },
      ],
    });
    
     <!-- 當路由跳轉的時候,可以直接使用路由的name,不必要寫多層 -->
        <router-link :to="{
          name: "message",
          query: { id: 3 },
          }">
           message
         </router-link>
    
        <router-link to="/about/message?id=3"> message </router-link>
    

    6.3 params 傳參(注意:使用 params 傳參的對象形式時,to 里面的內容必須得寫成 name 的形式)

    <router-link to="/about/message/9/杜蘭特"> message </router-link>
    
    <router-link
      :to="{
     name:'message',
     params: {
       id:9,
       name:'杜蘭特'
     }
    }"
    >
      message
    </router-link>
    
    const router = new VueRouter({
      routes: [
        {
          path: "/home",
          component: Home,
        },
        {
          path: "/about",
          component: About,
          children: [
            {
              name: "message",
              path: "message/:id/:name", // 使用占位符接收params傳參
              component: Message,
            },
          ],
        },
      ],
    });
    
    <p>ID : {{$route.params.id}}</p>
    <p>NAME : {{$route.params.name}}</p>
    

    6.4 路由的 props 配置

    const router = new VueRouter({
      routes: [
        {
          path: "/home",
          component: Home,
        },
        {
          path: "/about",
          component: About,
          children: [
            {
              path: "message",
              component: Message,
              // 寫法一:對象形式,會以props的形式傳給該組件
              // 缺點:數(shù)據只能是死數(shù)據
              props: {},
    
              // 寫法二:布爾形式,會把該組件收到的所有params參數(shù)以props形式傳給該組件
              // 缺點:只能接收params傳參
              props: true,
    
              // 寫法三:函數(shù)形式,從$route中拿到傳參
              props($route) {
                return {
                  id: $route.query.id,
                  title: $route.query.title,
                };
              },
            },
          ],
        },
      ],
    });
    
    export default {
      props: ["id", "title"],
    };
    
    <p>ID : {{id}}</p>
    <p>NAME : {{title}}</p>
    
  3. router-link 的 replace 屬性

    • router-link 默認是 push 模式,只需要在 router-link 的標簽中增加 :replace="true"屬性即可開啟 replace 模式
    <router-link to="/about/message" replace> message </router-link>
    
  4. 編程式路由

    <button @click="gotoMessage('7','durant')">消息</button>
    
    methods: {
      gotoMessage(id,title) {
        this.$router.replace("/about/message");
    
        this.$router.push({
         name:'message',
         query:{
           id,
           title
         }
        })
    
        this.$router.push({
          path:'/about/message',
          params:{
            id,
            title
          }
        })
      },
    }
    
    this.$router.back(); // 后退
    this.$router.forward(); // 前進
    this.$router.go(3); // 前進(傳正數(shù))后退(傳負數(shù))
    
  5. 緩存路由組件

    • 默認情況下,每次切換路由組件,都會重新渲染
    • 可以通過 <keep-alive> 標簽包裹需要緩存的組件,只要在<keep-alive>中包裹的組件都會被緩存
    • 緩存組件時,需要指定一個 name 屬性(name 對應的值是組件名,指的是 export default { name : Message }),這樣就會將指定的組件緩存起來
    <!-- 緩存一個 -->
    <keep-alive include="Message">
      <router-view></router-view>
    </keep-alive>
    
    <!-- 緩存多個 -->
     <keep-alive :include="['Message','News']">
      <router-view></router-view>
     </keep-alive>
    
  6. 新的生命周期(路由組件專屬)

    export default {
      activated(){
        // 進入組件時調用
      }
      deactivated(){
        // 離開組件時調用
      }
    }
    
  7. 全局路由守衛(wèi)

    import VueRouter from "vue-router";
    import Home from "../pages/Home";
    import About from "../pages/About";
    import Message from "../pages/Message";
    
    const router = new VueRouter({
      routes: [
        {
          name: "home",
          path: "/home",
          component: Home,
          meta: { title: "首頁" },
        },
        {
          name: "about",
          path: "/about",
          component: About,
          meta: { title: "關于" },
          children: [
            {
              name: "message",
              path: "message",
              component: Message,
              meta: {
                // 配置該組件是否需要權限校驗
                isAuth: true,
                title: "消息",
              },
            },
          ],
        },
      ],
    });
    
    router.beforeEach((to, from, next) => {
      // 判斷當前路由是否需要登錄權限
      if (to.meta.isAuth) {
        // 首先判斷該組件是否需要授權
        if (localStorage.getItem("token")) {
          // 再判斷是否已經登錄過,或者判斷是否包含token等信息
          next();
        } else {
          alert("您沒有權限查看該頁面");
          next("/home");
        }
      } else {
        next();
      }
    });
    
    router.afterEach((to, from) => {
      document.title = to.meta.title || "vue-router";
    });
    
    export default router;
    
  8. 獨享路由守衛(wèi)

    import VueRouter from "vue-router";
    import Home from "../pages/Home";
    import About from "../pages/About";
    import Message from "../pages/Message";
    
    const router = new VueRouter({
      routes: [
        {
          name: "home",
          path: "/home",
          component: Home,
          meta: { title: "首頁" },
        },
        {
          name: "about",
          path: "/about",
          component: About,
          meta: { title: "關于" },
          children: [
            {
              name: "message",
              path: "message",
              component: Message,
              meta: {
                isAuth: true,
                title: "消息",
              },
              beforeEnter: (to, from, next) => {
                // 寫法與全局前置路由守衛(wèi)一直
                // 需要注意的是,獨享路由守衛(wèi)只有前置
                console.log(to, from, next);
              },
            },
          ],
        },
      ],
    });
    
    export default router;
    
  9. 組件內路由守衛(wèi)(一般不用這個)

    export default {
      // 通過路由規(guī)則進入該組件時被調用
      beforeRouteEnter(to, from, next) {},
      // 通過路由規(guī)則離開該組件時被調用
      beforeRouteLeave(to, from, next) {},
    };
    
  10. history 和 hash 模式的區(qū)別

    const router = new VueRouter({
      mode: "history", // 默認是 hash
      routes: [...],
    });
    

    14.1 hash 在 url 中有#,history 沒有
    14.2 hash 的兼容性比 history 好
    14.3 history 模式需要后端配合,否則刷新頁面后會 404,而 hash 模式不需要

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

  • 一、Vue2 1.1 模板語法 1.1.1 模板的理解 html 中包含了一些 JS 語法代碼,語法分為兩種,分別...
    Cola_Mr閱讀 806評論 0 1
  • 初識Vue2.0 想讓Vue工作,就必須創(chuàng)建一個Vue實例,且要傳入一個配置對象 vue容器里的代碼依然符合htm...
    Zindex閱讀 725評論 0 0
  • 入口文件 vue-2.6.11\src\platforms\web\entry-runtime-with-comp...
    愛吃饅頭不吃辣閱讀 862評論 0 0
  • vue2 的雙向數(shù)據綁定是利用ES5 的一個 API[https://so.csdn.net/so/search?...
    Aven丶閱讀 519評論 0 0
  • vue特性與其他框架的區(qū)別 關于vue vue是一個簡潔且輕量化為主要特點的前端MVVM開發(fā)框架,vue使用組件化...
    Mr無愧于心閱讀 313評論 3 1

友情鏈接更多精彩內容