1. 程式人生 > 實用技巧 >總結vue知識體系之高階應用篇

總結vue知識體系之高階應用篇

### Vue.use

我們使用的第三方 Vue.js 外掛。如果外掛是一個物件,必須提供`install`方法。如果外掛是一個函式,它會被作為`install`方法。`install`方法呼叫時,會將`Vue`作為引數傳入。該方法需要在呼叫`new Vue()`之前被呼叫。

我們在使用外掛或者第三方元件庫的時候用到`Vue.use`這個方法,比如

```js
import iView from 'iview'
Vue.use(iView)
```

那麼`Vue.use`到底做了些什麼事情呢?我們先來看一下原始碼

```js
import { toArray } from '../util/index'

export 
function initUse(Vue: GlobalAPI) { Vue.use = function(plugin: Function | Object) { const installedPlugins = this._installedPlugins || (this._installedPlugins = []) if (installedPlugins.indexOf(plugin) > -1) { return this } // additional parameters const args = toArray(arguments, 1) args.unshift(
this) if (typeof plugin.install === 'function') { plugin.install.apply(plugin, args) } else if (typeof plugin === 'function') { plugin.apply(null, args) } installedPlugins.push(plugin) return this } } ``` 我們由以上可以看出,`plugin`引數為函式或者物件型別,首先`Vue`會去尋找這個外掛在已安裝的外掛列表裡有沒有,如果沒有,則進行安裝外掛,如果有則跳出函式,這保證外掛只被安裝一次。 接著通過`toArray`方法將引數變成陣列,再判斷`plugin`的`install`屬性是否為函式,或者`plugin`本身就是函式,最後執行`plugin.install`或者`plugin`的方法。 #### 舉個例子 下面我們來舉個實際例子
1、編寫兩個外掛 ```js const Plugin1 = { install(a) { console.log(a) } } function Plugin2(b) { console.log(b) } export { Plugin1, Plugin2 } ``` 2、引入並 use 這兩個外掛 ```js import Vue from 'vue' import { Plugin1, Plugin2 } from './plugins' Vue.use(Plugin1, '引數1') Vue.use(Plugin2, '引數2') ``` 此時我們執行專案程式碼就可以用到上面兩個外掛了。 ### Vue.mixin 混入 (mixin) 提供了一種非常靈活的方式,來分發 Vue 元件中的可複用功能。一個混入物件可以包含任意元件選項。當元件使用混入物件時,所有混入物件的選項將被“混合”進入該元件本身的選項。 1、定義一個 mixin.js ```js export default mixin { data() { return { name: 'mixin' } }, created() { console.log('mixin...', this.name); }, mounted() {}, methods: { //日期轉換 formatDate (dateTime, fmt = 'YYYY年MM月DD日 HH:mm:ss') { if (!dateTime) { return '' } moment.locale('zh-CN') dateTime = moment(dateTime).format(fmt) return dateTime } } } ``` 2、在vue檔案中使用mixin ```js import '@/mixin'; // 引入mixin檔案 export default { mixins: [mixin], //用法 data() { return { userName: "adimin", time: this.formatDate(new Date()) //這個vue檔案的資料來源data裡面的time就是引用混入進來的方法 } } } ``` 或者在全域性中使用在main.js中,所有頁面都能使用了 ```js import mixin from './mixin' Vue.mixin(mixin) ``` #### 合併選項 當元件和混入物件含有同名選項時,這些選項將以恰當的方式進行“合併”。 * `data`物件在內部會進行遞迴合併,並在發生衝突時以元件資料優先。 * 同名鉤子函式將合併為一個數組,因此都將被呼叫。混入物件的鉤子將在元件自身鉤子之前呼叫。 * 值為物件的選項,例如 `methods`、`components` 和 `directives`,將被合併為同一個物件。兩個物件鍵名衝突時,取元件物件的鍵值對。 ### Vue.extend ``Vue.extend`` 屬於 Vue 的全域性 API。它使用基礎 Vue 構造器,建立一個“子類”。引數是一個包含元件選項的物件。如下: ```js <div id="app"></div> var Profile = Vue.extend({ template: '<p>{{firstName}} {{lastName}}</p>', data: function () { return { firstName: 'Walter', lastName: 'White' } } }) // 建立 Profile 例項,並掛載到一個元素上。 new Profile().$mount('#app') ``` #### 應用例項 我們常用 `Vue.extend` 封裝一些全域性外掛,比如 `toast`, `diolog` 等。 下面以封裝一個 `toast` 元件為例。 1、編寫元件 * 根據傳入的 type 確定彈窗的型別(成功提示,失敗提示,警告,載入,純文字) * 設定彈窗消失的時間 ```html <template> <div> <transition name="fade"> <div class="little-tip" v-show="showTip"> <img src="/success.png" alt="" width="36" v-if="type=='success'" /> <img src="/fail.png" alt="" width="36" v-if="type=='fail'" /> <img src="/warning.png" alt="" width="36" v-if="type=='warning'" /> <img src="/loading.png" alt="" width="36" v-if="type=='loading'" class="loading" /> <span>{{msg}}</span> </div> </transition> </div> </template> <script> export default { data() { return { showTip: true, msg: '', type: '' } }, mounted() { setTimeout(() => { this.showTip = false }, 1500) } } </script> <style lang="less" scoped> /* 樣式略 */ </style> ``` 2、利用 `Vue.extend` 構造器把 `toast` 元件掛載到 `vue` 例項下 ```js import Vue from 'vue' import Main from './toast.vue' let Toast = Vue.extend(Main) let instance const toast = function(options) { options = options || {} instance = new Toast({ data: options }) instance.vm = instance.$mount() document.body.appendChild(instance.vm.$el) return instance.vm } export default toast ``` 3、在 `main.js` 引入 `toast` 組價並掛載在 `vue` 原型上 ```js import Vue from 'vue' import toast from './components/toast' Vue.prototype.$toast = toast ``` 4、在專案中呼叫 ```js this.$toast({ msg: '手機號碼不能為空' }) this.$toast({ msg: '成功提示', type: 'success' }) ``` #### Vue.extend 和 Vue.component 的區別 * `component`是需要先進行元件註冊後,然後在 `template` 中使用註冊的標籤名來實現元件的使用。`Vue.extend` 則是程式設計式的寫法。 * 控制`component`的顯示與否,需要在父元件中傳入一個狀態來控制或者在元件外部用 `v-if/v-show` 來實現控制,而 `Vue.extend` 的顯示與否是手動的去做元件的掛載和銷燬。 ### Vue.directive 註冊或獲取全域性指令。指令定義函式提供了幾個鉤子函式(可選): * bind: 只調用一次,指令第一次繫結到元素時呼叫,可以定義一個在繫結時執行一次的初始化動作。 * inserted: 被繫結元素插入父節點時呼叫(父節點存在即可呼叫,不必存在於 document 中)。 * update: 被繫結元素所在的模板更新時呼叫,而不論繫結值是否變化。通過比較更新前後的繫結值。 * componentUpdated: 被繫結元素所在模板完成一次更新週期時呼叫。 * unbind: 只調用一次, 指令與元素解綁時呼叫。 #### 應用例項 下面封裝一個複製貼上文字的例子。 1、編寫指令 `copy.js` ```js const vCopy = { bind (el, { value }) { el.$value = value // 用一個全域性屬性來存傳進來的值 el.handler = () => { if (!el.$value) { alert('無複製內容') return } // 動態建立 textarea 標籤 const textarea = document.createElement('textarea') // 將該 textarea 設為 readonly 防止 iOS 下自動喚起鍵盤,同時將 textarea 移出可視區域 textarea.readOnly = 'readonly' textarea.style.position = 'absolute' textarea.style.left = '-9999px' // 將要 copy 的值賦給 textarea 標籤的 value 屬性 textarea.value = el.$value // 將 textarea 插入到 body 中 document.body.appendChild(textarea) // 選中值並複製 textarea.select() // textarea.setSelectionRange(0, textarea.value.length); const result = document.execCommand('Copy') if (result) { alert('複製成功') } document.body.removeChild(textarea) } // 繫結點選事件,就是所謂的一鍵 copy 啦 el.addEventListener('click', el.handler) }, // 當傳進來的值更新的時候觸發 componentUpdated (el, { value }) { el.$value = value }, // 指令與元素解綁的時候,移除事件繫結 unbind (el) { el.removeEventListener('click', el.handler) } } export default vCopy ``` 2、註冊指令 ```js import copy from './copy' // 自定義指令 const directives = { copy } // 這種寫法可以批量註冊指令 export default { install (Vue) { Object.keys(directives).forEach((key) => { Vue.directive(key, directives[key]) }) } } ``` 3、在 `main.js` 引入並 `use` ```js import Vue from 'vue' import Directives from './JS/directives' Vue.use(Directives) ``` 這樣就可以在專案直接用 `vCopy` 指令了。