vue全家桶開發的一些小技巧和注意事項

前言

用vue全家桶開發一年多了,踩過很多坑,也解決了不少的問題,把其中的一些點記錄下來,但願能幫到你們。如下內容基於最新版的vue + vuex + vue-router + axios + less + elementUI,vue腳手架是vue-cli3。javascript

css的scoped屬性

vue 爲了防止 css 污染,當組件的 <style> 標籤有 scoped 屬性時,它的 css 只做用於當前組件中的元素。實現原理很簡單,給當前組件中的每一個標籤都加上惟一的自定義屬性:data-v-惟一的屬性,而後 css 選擇器都加上屬性選擇器.article-title[data-v-惟一的屬性],這樣這個 css 只會匹配到當前頁面的這個元素。php

注意:每一個組件的最外層的標籤會帶上父組件的data-v-屬性,也就是這個標籤會被父組件的樣式匹配到,因此父組件儘可能不要使用標籤選擇器,這個標籤不要使用父組件中的 id 或者 class。css

css-scoped

在父組件想修改子組件的css(修改elementUI組件的樣式),咱們能夠藉助深度做用選擇器 >>>html

div >>> .el-input{
    width: 100px;
}
/* sass/less的話可能沒法識別,這時候須要使用 /deep/ 選擇器。 */
div /deep/ .el-input{
    width: 100px;
}
複製代碼

深度做用選擇器會去掉後面元素的屬性選擇器[data-v-],即上面代碼會編譯成:div[data-v-12345667] .el-input{}。就能夠匹配到子組件的元素,從而覆蓋樣式。vue

父子組件的生命週期鉤子函數執行前後順序

組件的生命週期鉤子函數是到了某個生命週期點就會觸發,而不是在這個鉤子函數中進行生命週期,好比說DOM加載好了,就會觸發mounted 鉤子函數,因此在created 裏面寫一個延遲定時器,mounted 鉤子不會等定時器執行。java

各個週期鉤子函數觸發的時間點參考(圖來源於網絡)ios

life

關於父子組件的生命週期:不一樣的鉤子函數有不一樣的表現。父組件的虛擬 DOM 先初始化好了(beforeMount),纔會去初始化子組件的虛擬 DOM (beforeMount),而 mounted 事件,等價於 window.onload,子組件 DOM 沒加載好,父組件 DOM 永遠不可能加載好。因此基本生命週期鉤子函數執行順序是:父beforeCreate -> 父created -> 父beforeMount -> 子beforeCreate -> 子created -> 子beforeMount -> 子mounted -> 父mountedvue-router

父子組件的update和beforeUpdate執行前後順序:數據修改+虛擬DOM準備好會觸發beforeUpdate,換句話說beforeUpdate等價於beforeMount,而update等價於mounted。因此前後順序是: 父beforeUpdate -> 子beforeUpdate -> 子update -> 父update。vuex

同理beforeDestorydestoryed的前後順序是:父beforeDestory -> 子beforeDestory -> 子destoryed -> 父destoryed。vue-cli

生命週期鉤子函數其實也能夠寫成數組的形式:mounted: [mounted1, mounted2],同一個生命週期能夠觸發多個函數,這也是mixin(混入)的原理,mixin裏面也能夠寫生命週期鉤子,最終會和組件裏面的生命週期鉤子函數一塊兒變成數組形式,mixin裏面的鉤子函數會先執行。

異步請求數據在哪一個鉤子函數中執行比較好

不少人以爲在 created 事件裏面把數據請求到,而後一塊兒生成虛擬 DOM,再渲染會更好。實際上呢,請求是須要時間的,並且這個時間具備不穩定性,極可能 vue 的虛擬 DOM 準備好了,你的數據才請求到,而後又得更新一遍虛擬 DOM,再渲染,極大地延長了白屏時間,用戶體驗很很差。而在 mounted 事件請求數據呢,靜態頁面會先渲染好,等數據好了,再更新部分 DOM 便可。

補充:經掘友指出,這裏理解有誤,抱歉。

生命週期鉤子函數的中異步會放入事件隊列,而不會在這個鉤子函數中執行。也就是說你在 createdmounted 中請求數據是同樣的,都不會當即更新數據,因此不會致使虛擬DOM從新加載,也不影響頁面中靜態的部分加載。生命週期鉤子函數中的異步賦值,vue會在一遍流程走完以後執行update。另外,給數據賦值而後更新 DOM 也是異步的,偵聽到數據變化,Vue 將開啓一個隊列,並緩衝在同一事件循環中發生的全部數據變動,去掉重複賦值而後更新。

生命週期鉤子函數中的異步行爲測試:

export default {
    data(){
        return {
            list:[],
        }
    },
    methods:{
        getData(){
            //生成指定範圍的隨機整數
            const randomNum = (min, max) => Math.floor(Math.random() * (max - min + 1)) + min; 
            //生成固定長度的非空數組
            const randomArr = length => Array.from({ length }, (item, index) => index * 2); 
            const time = randomNum(100,3000);//模擬請求時間
            console.log('getData start');
            return new Promise(resolve => {
                setTimeout(() => {
                    const arr = randomArr(10);
                    resolve(arr);
                },time)
            })
        }
    },
    async created(){
        console.log('created');
        this.list = await this.getData();
        console.log('getData end');
    },
    beforeMount() {
        console.log('beforeMount');
    },
    mounted(){
        console.log('mounted');
    },
    updated(){
        console.log('updated');
    }
}
複製代碼

結果以下圖,因此在 created 中和 mounted 中請求數據,數據的更新時間是同樣的,在 created 中發起請求,能夠更早的請求到數據。而且使用服務端渲染SSR的時候, mounted 鉤子不會加載。

result

父組件監聽子組件的生命週期

能夠寫自定義事件,而後在子組件的生命週期函數中觸發這個自定義事件,可是不優雅,咱們可使用 hook:

<child @hook:created="childCreated"></child>
複製代碼

從 A 頁面切換到 B 頁面,A 頁面中有一個定時器,到了 B 頁面用不上,須要在離開 A 頁面的時候清除掉,辦法很簡單,在 A 頁面的生命週期鉤子函數beforeDestory或者路由鉤子函數beforeRouteLeave裏面清除掉就行,可是問題來了,怎麼拿到定時器呢?把定時器寫到 data 裏面,可行可是不優雅,咱們有以下寫法:

//在初始化定時器以後
this.$once('hook:beforeDestory',()=>{
    clearInterval(timer);
})
複製代碼

is屬性的妙用

因爲 HTML 標籤的限制,tr 標籤裏面只能有 th, td 標籤,而寫自定義標籤則會被解析到 tr 標籤外層,因此這時候咱們能夠用 is 屬性

<tr>
    <td is="child">
</tr>
複製代碼

最近有個頁面有大量的 SVG 圖標,我將每個 SVG 都寫成了一個組件。因爲 SVG 組件名稱又各不相同,因此須要動態標籤來表示:

<!-- 假設咱們的數據以下 -->
arr: [ { id: 1, name: 'first' }, { id: 2, name: 'second' }, { id: 3, name: 'third' }, ]

<!-- 原本須要這樣寫 -->
<div v-for="item in arr" :key="item.id">
    <p>item.name</p>
    <svg-first v-if="item.id===1"></svg-first>
    <svg-second v-if="item.id===2"></svg-second>
    <svg-third v-if="item.id===3"></svg-third>
</div>

<!-- 其實這樣寫更優雅 -->
<div v-for="item in arr" :key="item.id">
    <p>item.name</p>
    <component :is="'svg'+item.name"></component>
</div>
複製代碼

給事件傳額外參數

原生 DOM 事件綁定的函數的第一個參數都會是事件對象event,可是有時候咱們想給這個函數傳其餘的參數,直接傳會覆蓋掉event,咱們能夠這麼寫<div @click="clickDiv(params,$event)"></div>,變量$event就表明事件對象。

若是要傳的變量不是事件對象呢?在使用 elementUI 的時候碰到這麼一個狀況,在表格中使用了下拉菜單組件,代碼以下:

<el-table-column label="日期" width="180">
    <template v-slot="{row}">
        <el-dropdown @command="handleCommand">
            <span>
                下拉菜單<i class="el-icon-arrow-down el-icon--right"></i>
            </span>
            <template #dropdown>
                <el-dropdown-menu>
                    <el-dropdown-item command="a">黃金糕</el-dropdown-item>
                    <el-dropdown-item command="b">獅子頭</el-dropdown-item>
                </el-dropdown-menu>
            </template>
        </el-dropdown>
    </template>
</el-table-column>
複製代碼

下拉菜單事件 command 函數自帶一個參數,爲下拉選中的值,這個時候咱們想把表格數據傳過去,若是@command="handleCommand(row)"這樣寫,就會覆蓋掉自帶的參數,該怎麼辦呢?這時候咱們能夠藉助箭頭函數:@command="command => handleCommand(row,command)",完美解決傳參問題。

順便說一下,elementUI 的表格能夠用變量$index表明當前的列數,和$event同樣的使用:

<el-table-column label="操做">
    <template v-slot="{ row, $index }">
        <el-button @click="handleEdit($index, row)">編輯</el-button>
    </template>
</el-table-column>
複製代碼

經掘友指點,默認參數有多個(或者未知個數)的時候,能夠這樣寫:@current-change="(...defaultArgs) => treeclick(ortherArgs, ...defaultArgs)"

v-slot 語法

v-slot 的用法(slot 語法已經廢棄):至關於在組件中留一個空位,使用該組件的時候能夠傳一些標籤過去,插入到對應的空位。能夠有多個空位,取不一樣的名字便可,默認是 default。同時還能夠將一些數據傳過去,簡寫是#

<!-- 子組件 -->
<div class="container">
    <header>
        <slot name="header"></slot>
    </header>
    <main>
        <slot></slot>
    </main>
    <footer>
        <slot name="footer"></slot>
    </footer>
</div>
<!-- 父組件 -->
<base-layout>
    <!-- 插槽能夠簡寫爲# -->
    <template #header="data">
        <h1>Here might be a page title</h1>
    </template>
    <!-- v-slot:default可省略 -->
    <div v-slot:default>
        <p>A paragraph for the main content.</p>
        <p>And another one.</p>
    </div>
    <!-- 可使用解構 -->
    <template #footer="{ user }">
        <p>Here's some contact info</p>
    </template>
</base-layout>
複製代碼

總結:

  • 其餘名稱的 slot(非 default)僅能用於 template 標籤。
  • 插槽裏面的標籤拿不到傳給子標籤的數據(插槽至關於孫子組件):
<child :data="data">
    <div>在這裏訪問不到data數據</div>
</child>
複製代碼
  • 插槽可使用解構語法v-slot="{ user }"

子組件修改父組件傳過來的值

v-model在使用的時候很像雙向綁定的,可是 Vue 是單項數據流,v-model 只是語法糖而已:父組件用v-bind將值傳給子組件,子組件經過 change/input 事件觸發修改父組件的值。

<input v-model="inputValue" />
<!-- 等價於 -->
<input :value="inputValue" @change="inputValue = $event.target.value" />
複製代碼

v-model 不只僅能在 input 上用,在組件上也能使用。

vue 組件間傳遞數據是單向的,即數據老是由父組件傳遞到子組件,子組件在其內部能夠有本身維護的數據,但它無權修改父組件傳遞給它的數據,咱們也能夠參照v-model語法糖進行修改父組件的值,可是每次都這樣寫太麻煩了,vue 提供了一個修飾符.sync,用法以下:

<child :value.sync="inputValue"></child>
<!-- 子組件 -->
<script> export default { props: { //props能夠設置值得類型,默認值,是否必傳以及校驗函數 value: { type: [String, Number], required: true, }, }, //用一個變量中轉,子組件中就用_value就不會直接修改父組件的值 computed: { _value: { get() { return this.value; }, set(val) { this.$emit('update:value', val); }, }, }, }; </script>
複製代碼

父組件經過 ref 訪問到子組件

雖然 vue 提供 $parent$children來訪問父/子組件,可是組件的父組件/子組件存在不少不肯定性,例如組件被複用,他的父組件有多種狀況。咱們能夠經過 ref 訪問到子組件的數據和方法。

<child ref="myChild"></child>
<script> export default { async mounted() { await this.$nextTick(); console.dir(this.$refs.myChild); }, }; </script>
複製代碼

注意:

  • ref 必須等 DOM 加載好了才能夠訪問
  • 雖然 mounted 生命週期 DOM 已經加載好了,可是爲了以防萬一,咱們可使用 $nextTick 函數

背景圖、css 的@import 使用路徑別名

在用 Webpack 處理打包時,可將某一目錄配置一個別名,代碼中就能使用與別名的相對路徑引用資源

import tool from '@/utils/test'; // Webpack 能正確識別並打包。
複製代碼

可是在 css 文件,如 less, sass, stylus 中,使用 @import "@/style/theme" 的語法引用相對 @ 的目錄確會報錯。 解決辦法是是在引用路徑的字符串最前面添加上 ~ 符號。

  • css module 中: @import "~@/style/theme.less"
  • css 屬性中: background: url("~@/assets/xxx.jpg")
  • html 標籤中: <img src="~@/assets/xxx.jpg">

vue-router 的 hash 模式和 history 模式

咱們先來看一個完整的 URL:https://www.baidu.com/blog/guide/vuePlugin.html#vue-router。其中 https://www.baidu.com 是網站根目錄,/blog/guide/是子目錄,vuePlugin.html是子目錄下的文件(若是隻有目錄,沒有指定文件,會默認請求index.html文件),而#vue-router就是哈希值。

vue 是單頁應用,打包以後只有一個 index.html,將他部署到服務器上以後,訪問對應文件的目錄就是訪問這個文件。

hash 模式:網址後面跟着 hash 值,hash 值對應每個 router 的名稱,hash 值改變意味着router 改變,監聽 onhashchange 事件,來替換頁面內容。

history 模式:網址後面跟着‘假的目錄名’,其值就是 router 的名稱,而瀏覽器會去請求這個目錄的文件(並不存在,會 404),因此 history 模式須要服務器配合,配置 404 頁面重定向到到咱們的 index.html,而後 vue-router 會根據目錄的名稱來替換頁面內容。

優缺點:

  1. hash 模式的 # 號很醜,使用的是 onhashchange 事件切換路由,兼容性會好一點,不須要服務器配合
  2. history 模式好看點,可是本地開發、網站上線,都須要服務器額外配置,而且還須要本身寫 404 頁面,使用的是 HTML5history API,兼容性差一點。

二者的配置區別在於:

const router = new VueRouter({
    mode: 'history', //"hash"模式是默認的,無需配置
    base: '/',//默認配置
    routes: [...]
})
複製代碼

vue-cli3 的 vue.config.js 配置:

module.exports = {
    publicPath: "./", // hash模式打包用
    // publicPath: "/", // history模式打包用
    devServer: {
        open: true,
        port: 88,
        // historyApiFallback: true, //history模式本地開發用
    }
}
複製代碼

若是是網站部署在根目錄,routerbase 就不用填。若是整個單頁應用服務在 /app/ 下,而後 base 就應該設爲 "/app/",同時打包配置(vue.config.js)的 publicPath 也應該設置成/app/

vue-cli3生成新項目的時候會有選擇路由的模式,選擇history模式就會幫你都配置好。

vue-router的鉤子函數

鉤子函數分三種:組件內鉤子,全局鉤子,路由獨享鉤子。

APP.vue沒有組件內鉤子函數,由於APP.vue是頁面的入口,這個組件是一定會加載的,而使用組件內鉤子函數能夠阻止組件加載。

全局鉤子主要用於路由鑑權,可是消耗很大。組件內的鉤子beforeRouteLeave主要用於用戶離開前的提示(好比說有未保存的文章),這個鉤子有一些坑:hash模式下,瀏覽器的後退按鈕沒法觸發這個鉤子函數。同時咱們還能夠監聽用戶的關閉當前窗口/瀏覽器事件:

window.onbeforeunload = e => "肯定離開當前頁面,你的修改將不會被保存!";
複製代碼

爲了防止惡意網站,用戶關閉窗口/瀏覽器事件是不可阻止的,只能提示,並且不一樣的瀏覽器兼容性也不一樣。

Vuex持久化存儲

Vuex 中的數據,刷新頁面以後就會丟失。要實現持久化存儲須要藉助本地存儲(cookie 和 storage 等),通常是登陸以後返回的數據(角色,權限,token 等)須要存儲到 Vuex,因此咱們能夠在登陸頁將數據存儲到本地,而在主頁面(除了登陸頁,其餘全部頁面的入口)進入以前(beforeCreate 或者路由鉤子 beforeRouteEnter)讀取出來,並提交到 Vuex 就行了。這樣即便刷新,也會觸發主頁面的進入鉤子函數,會被提交到 Vuex

beforeRouteEnter (to, from, next) {
    const token = localStorage.getItem('token');
    let right = localStorage.getItem('right');
    try{
        right = JSON.parse(right);
    }catch{
        next(vm => {
            //彈窗採用elementUI
            vm.$alert('獲取權限失敗').finally(() => {
                vm.$router.repalce({name:'login'})
            })
        })
    }
    if(!right || !token){
        next({name:'login',replace:true})
    }else{
        next(vm => {
            //這裏面的事件會在mounted以後觸發
            vm.$store.commit('setToken',token);
    	    vm.$store.commit('setRight',right);
        })
    }
}
複製代碼

beforeRouteEnter的回調會在mounted鉤子以後觸發,這就比較蛋疼了。而主頁面的mounted會在全部子組件的mounted以後觸發,因此咱們能夠這樣寫。

import store from '^/store';//將實例化的store引入進來

beforeRouteEnter (to, from, next) {
    const token = localStorage.getItem('token');
    if(!token){
        next({name:'login',replace:true})
    }else{
        store.commit('setToken',token);
        next();
    }
}
複製代碼

要想實現數據修改以後仍能持久化存儲,咱們能夠先把數據存到localstorage,而後監聽window.onstorage事件,數據有修改提交到Vuex

mutations 裏面觸發 action

mutations 是同步修改 state 的值,假如另外一個值是異步獲取(action)的,依賴於這個同步的值的修改,須要在 mutations 裏面賦值以前觸發 action 裏面的事件,咱們能夠給實例化的 Vuex 命名,在 mutations 裏面拿到 store 對象。

const store = new Vuex.Store({
    state: {
        age: 18,
        name: 'zhangsan',
    },
    mutations: {
        setAge(state, val) {
            // 假如age變化了以後,name也要跟着變化
            // 須要在每次給age賦值的時候,同步觸發action裏面的getName
            state.age = val;
            store.dispatch('getName');
        },
        setName(state, val) {
            state.name = val;
        },
    },
    actions: {
        getName({ commit }) {
            const name = fetch('name'); //從接口異步獲取
            commit('setName', name);
        },
    },
});
複製代碼

Vue.observable進行組件通訊

若是項目很小,不須要用到 vuex ,能夠用Vue.observable來模擬一個:

//store.js
import Vue from 'vue';

const store = Vue.observable({ name: '張三', age: 20 });
const mutations = {
    setAge(age) {
        store.age = age;
    },
    setName(name) {
        store.name = name;
    },
};
export { store, mutations };
複製代碼

axios 的 qs 插件

get 請求的數據放在 url 裏面,相似於http://www.baidu.com?a=1&b=2,其中a=1&b=2就是 get 的參數,而對於 post 請求,參數放到 body 裏面,經常使用的數據格式有表單數據和 json 數據,二者的差別就是數據格式不一樣,表單數據編碼格式和 get 同樣,只不過是放在 body 裏面,而 json 數據則是 json 字符串

qs 基本使用:

import qs from 'qs'; //qs是axios裏面自帶的,因此直接引入就能夠了
const data = qs.stringify({
    username: this.formData.username,
    oldPassword: this.formData.oldPassword,
    newPassword: this.formData.newPassword1,
});
this.$http.post('/changePassword.php', data);
複製代碼

qs.parse()是將 URL 解析成對象的形式,qs.stringify()是將對象 序列化成 URL 的形式,以&進行拼接。而對於不一樣的數據格式,axios 會自動設置對應的content-type,不須要手動設置。

  • 表單數據(不帶文件)的 content-type 是application/x-www-form-urlencoded
  • 表單數據(帶文件)的 content-type 是multipart/form-data
  • json 數據的 content-type 是application/json

碰到過一次接口須要我用表單傳一個數組。假設數據是arr = [1,2,3]若是直接使用 qs.stringify(),則數據會變成arr[]=1&arr[]=2&arr[]=3,很容易看出來,多了一個[],讓接口把參數名改爲arr[]就能用,可是這樣很差。不過能夠發現,表單傳數組的本質就是同名參數傳屢次,這時候咱們也能夠這樣:

const data = new FormData();
arr.forEach(item => {
	data.append('arr', item);
});
複製代碼

測試一下,完美解決,可是事情到這裏還沒完,翻一下qs 官方文檔,qs 轉換支持第二個參數,完美解決咱們的問題。

const data = qs.stringify(arr, { arrayFormat: 'repeat' }); // arr=1&arr=2&arr=3
複製代碼

elementUI 的一些總結

  1. 表單驗證同步寫法,避免多層嵌套函數
const valid = await new Promise(resolve => this.$refs.form.validate(resolve));
if (!valid) return
複製代碼
  1. 按需引入以後級聯菜單高度撐滿屏幕。解決辦法:加一句全局樣式
.el-cascader-menu > .el-scrollbar__wrap{
    height: 250px;
}
複製代碼
  1. 級聯菜單的數據是按需獲取的無法回顯。解決辦法:根據已有的路徑數據去請求樹數據,而後給級聯菜單加一個v-if,等數據都請求好了再顯示出來。好比說省市縣三級聯動數據,已知用戶選擇的是廣東省-深圳市-南山區,那麼分別去請求全部省、廣東省、深圳市的數據,而後將數據拼成一個 tree ,綁定到級聯菜單,而後設置v-if="true"
  2. 表格高度自適應,能夠給表格外層加一個 div ,而後給這個 div 計算高度(或者彈性盒子自適應高度),表格屬性height="100%"
<div class="table-wrap">
    <el-table :height="100%"></el-table>
</div>
複製代碼
/* less寫法 */
.table-wrap{
    height: calc(~"100vh - 200px"); 
    /* 部分版本這樣寫會失效,須要加上下面一句 */
    /deep/ .el-table{
        height: 100% !important;
    }
}
複製代碼
  1. 使用多個 upload 組件,須要將這些文件一塊兒上傳到服務器。能夠經過this.$refs.poster.uploadFiles拿到文件對象。而後本身手動組裝成表單數據。
<el-form-item label="模板文件:" required>
    <el-upload ref="template" action="" :auto-upload="false" accept="application/zip" :limit="1">
        <span v-if="temForm.id">
            <el-button slot="trigger" type="text"><i class="el-icon-refresh"></i>更新文件</el-button>
        </span>
        <el-button slot="trigger" size="mini" type="success" v-else>上傳文件</el-button>
    </el-upload>
</el-form-item>
<el-form-item label="模板海報:" required>
    <el-upload action="" :auto-upload="false" ref="poster" accept="image/gif,image/jpeg,image/png,image/jpg" :show-file-list="false" :on-change="changePhoto">
        <img :src="previewUrl" @load="revokeUrl" title="點擊上傳海報" alt="資源海報" width="250" height="140">
        <template #tip>
            <div>tips: 建議上傳尺寸250*140</div>
        </template>
    </el-upload>
 </el-form-item>
複製代碼
methods:{
    //選擇圖片以後替換舊圖片和顯示略縮圖
    changePhoto(file, fileList) {
    //建立的Blob URL可直接預覽圖片
        this.previewUrl = window.URL.createObjectURL(file.raw);
        if (fileList.length > 1) {
            fileList.shift();
        }
    },
    revokeUrl(e) {
        //圖片加載完成以後銷燬Blob URL
        if (e.target.src.startsWith("blob:")) window.URL.revokeObjectURL(e.target.src);
   },
    //提交表單數據
    async submitData() {
        const template = this.$refs.template.uploadFiles[0], //模板文件
            poster = this.$refs.poster.uploadFiles[0], //海報文件
            formData = new FormData();
        if (!template) return this.$message.warning("必須選擇模板文件");
        if (!poster) return this.$message.warning("必須選擇海報文件");
        formData.append("zip", template.raw);
        formData.append("poster", poster.raw);
        const res = await this.$http.post('url', formData);
    },
}
複製代碼
  1. 使用VueI18n國際化,須要將elementUI的語言包和項目中的語言包合併成一個。
import VueI18n from "vue-i18n";
import zhLocale from './locales/zh.js';/* 引入本地簡體中文語言包 */
import zhTWLocale from './locales/zh-TW.js';/* 引入本地繁體中文語言包 */
import enLocale from './locales/en.js';/* 引入本地英語語言包 */
import zhElemment from 'element-ui/lib/locale/lang/zh-CN'//引入elementUI簡體中文語言包
import zhTWElemment from 'element-ui/lib/locale/lang/zh-TW'//引入elementUI繁體中文語言包
import enElemment from 'element-ui/lib/locale/lang/en'//引入elementUI英語語言包

Vue.use(VueI18n);
const messages = {//語言包
    zh: Object.assign(zhLocale, zhElemment),//本地語言包加入elementUI的語言包
    'zh-TW': Object.assign(zhTWLocale, zhTWElemment),//本地語言包加入elementUI的語言包
    en: Object.assign(enLocale, enElemment)//本地語言包加入elementUI的語言包
};
const i18n = new VueI18n({
    locale: "zh", //zh默認是簡體中文
    messages
});

Vue.use(ElementUI, {
    i18n: (key, value) => i18n.t(key, value)
})
複製代碼

最後

有寫錯的,或者有什麼問題,歡迎你們評論

相關文章
相關標籤/搜索