vue 組件的理解

Vue.mixin

混入 (mixin) 提供了一種非常靈活的方式缘挑,來(lái)分發(fā) Vue 組件中的可復(fù)用功能。一個(gè)混入對(duì)象可以包含任意組件選項(xiàng)蝌数。當(dāng)組件使用混入對(duì)象時(shí)哩盲,所有混入對(duì)象的選項(xiàng)將被“混合”進(jìn)入該組件本身的選項(xiàng)。

  • 定義一個(gè) mixin.js
export default mixin {
 data() {
  return {
   name: 'mixin'
  }
 },
 created() {
  console.log('mixin...', this.name);
 },
 mounted() {},
 methods: {  //日期轉(zhuǎn)換
   formatDate (dateTime, fmt = 'YYYY年MM月DD日 HH:mm:ss') {
     if (!dateTime) {
      return ''
     }
     moment.locale('zh-CN')
     dateTime = moment(dateTime).format(fmt)
     return dateTime
  }
 }
}
  • 在vue文件中使用mixin
import '@/mixin'; // 引入mixin文件
export default {
 mixins: [mixin],  //用法
 data() {
  return {
   userName: "adimin",
   time: this.formatDate(new Date()) //這個(gè)vue文件的數(shù)據(jù)源data里面的time就是引用混入進(jìn)來(lái)的方法
  }
 }
} 
  • 或者在全局中使用在main.js中滓侍,所有頁(yè)面都能使用了
import mixin from './mixin'
Vue.mixin(mixin)  

合并選項(xiàng)
當(dāng)組件和混入對(duì)象含有同名選項(xiàng)時(shí)密浑,這些選項(xiàng)將以恰當(dāng)?shù)姆绞竭M(jìn)行“合并”。

data對(duì)象在內(nèi)部會(huì)進(jìn)行遞歸合并粗井,并在發(fā)生沖突時(shí)以組件數(shù)據(jù)優(yōu)先尔破。
同名鉤子函數(shù)將合并為一個(gè)數(shù)組街图,因此都將被調(diào)用±凉梗混入對(duì)象的鉤子將在組件自身鉤子之前調(diào)用餐济。
值為對(duì)象的選項(xiàng),例如 methods胆剧、components 和 directives絮姆,將被合并為同一個(gè)對(duì)象。兩個(gè)對(duì)象鍵名沖突時(shí)秩霍,取組件對(duì)象的鍵值對(duì)篙悯。

Vue.extend

Vue.extend 屬于 Vue 的全局 API。它使用基礎(chǔ) Vue 構(gòu)造器铃绒,創(chuàng)建一個(gè)“子類(lèi)”鸽照。參數(shù)是一個(gè)包含組件選項(xiàng)的對(duì)象。如下:

<div id="app"></div>

var Profile = Vue.extend({
  template: '<p>{{firstName}} {{lastName}}</p>',
  data: function () {
    return {
      firstName: 'Walter',
      lastName: 'White'
    }
  }
})
  • 創(chuàng)建 Profile 實(shí)例颠悬,并掛載到一個(gè)元素上矮燎。
new Profile().$mount('#app')

應(yīng)用實(shí)例
我們常用 Vue.extend 封裝一些全局插件,比如 toast赔癌, diolog 等诞外。
下面以封裝一個(gè) toast 組件為例。

1.編寫(xiě)組件

根據(jù)傳入的 type 確定彈窗的類(lèi)型(成功提示灾票,失敗提示峡谊,警告,加載刊苍,純文字)
設(shè)置彈窗消失的時(shí)間

<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 構(gòu)造器把 toast 組件掛載到 vue 實(shí)例下

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 組價(jià)并掛載在 vue 原型上

import Vue from 'vue'
import toast from './components/toast'
Vue.prototype.$toast = toast

4.在項(xiàng)目中調(diào)用

this.$toast({ msg: '手機(jī)號(hào)碼不能為空' })

this.$toast({
  msg: '成功提示',
  type: 'success'
})
  • Vue.extend 和 Vue.component 的區(qū)別
    component是需要先進(jìn)行組件注冊(cè)后靖苇,然后在 template 中使用注冊(cè)的標(biāo)簽名來(lái)實(shí)現(xiàn)組件的使用。Vue.extend 則是編程式的寫(xiě)法班缰。
    控制component的顯示與否贤壁,需要在父組件中傳入一個(gè)狀態(tài)來(lái)控制或者在組件外部用 v-if/v-show 來(lái)實(shí)現(xiàn)控制,而 Vue.extend 的顯示與否是手動(dòng)的去做組件的掛載和銷(xiāo)毀埠忘。

Vue.directive

注冊(cè)或獲取全局指令脾拆。指令定義函數(shù)提供了幾個(gè)鉤子函數(shù)(可選):

bind: 只調(diào)用一次,指令第一次綁定到元素時(shí)調(diào)用莹妒,可以定義一個(gè)在綁定時(shí)執(zhí)行一次的初始化動(dòng)作名船。
inserted: 被綁定元素插入父節(jié)點(diǎn)時(shí)調(diào)用(父節(jié)點(diǎn)存在即可調(diào)用,不必存在于 document 中)旨怠。
update: 被綁定元素所在的模板更新時(shí)調(diào)用渠驼,而不論綁定值是否變化。通過(guò)比較更新前后的綁定值鉴腻。
componentUpdated: 被綁定元素所在模板完成一次更新周期時(shí)調(diào)用迷扇。
unbind: 只調(diào)用一次百揭, 指令與元素解綁時(shí)調(diào)用。

應(yīng)用實(shí)例
下面封裝一個(gè)復(fù)制粘貼文本的例子蜓席。

1.編寫(xiě)指令 copy.js

const vCopy = { 
  bind (el, { value }) {
    el.$value = value // 用一個(gè)全局屬性來(lái)存?zhèn)鬟M(jìn)來(lái)的值
    el.handler = () => {
      if (!el.$value) {
        alert('無(wú)復(fù)制內(nèi)容')
        return
      }
      // 動(dòng)態(tài)創(chuàng)建 textarea 標(biāo)簽
      const textarea = document.createElement('textarea')
      // 將該 textarea 設(shè)為 readonly 防止 iOS 下自動(dòng)喚起鍵盤(pán)器一,同時(shí)將 textarea 移出可視區(qū)域
      textarea.readOnly = 'readonly'
      textarea.style.position = 'absolute'
      textarea.style.left = '-9999px'
      // 將要 copy 的值賦給 textarea 標(biāo)簽的 value 屬性
      textarea.value = el.$value
      // 將 textarea 插入到 body 中
      document.body.appendChild(textarea)
      // 選中值并復(fù)制
      textarea.select()
      // textarea.setSelectionRange(0, textarea.value.length);
      const result = document.execCommand('Copy')
      if (result) {
        alert('復(fù)制成功')
      }
      document.body.removeChild(textarea)
    }
    // 綁定點(diǎn)擊事件,就是所謂的一鍵 copy 啦
    el.addEventListener('click', el.handler)
  },
  // 當(dāng)傳進(jìn)來(lái)的值更新的時(shí)候觸發(fā)
  componentUpdated (el, { value }) {
    el.$value = value
  },
  // 指令與元素解綁的時(shí)候厨内,移除事件綁定
  unbind (el) {
    el.removeEventListener('click', el.handler)
  }
}

export default vCopy

2.注冊(cè)指令

import copy from './copy'
// 自定義指令
const directives = {
  copy
}
// 這種寫(xiě)法可以批量注冊(cè)指令
export default {
  install (Vue) {
    Object.keys(directives).forEach((key) => {
      Vue.directive(key, directives[key])
    })
  }
}

3.在 main.js 引入并 use

import Vue from 'vue'
import Directives from './JS/directives'
Vue.use(Directives)

這樣就可以在項(xiàng)目直接用 vCopy 指令了祈秕。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市雏胃,隨后出現(xiàn)的幾起案子请毛,更是在濱河造成了極大的恐慌,老刑警劉巖瞭亮,帶你破解...
    沈念sama閱讀 222,000評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件方仿,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡街州,警方通過(guò)查閱死者的電腦和手機(jī)兼丰,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,745評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門(mén)玻孟,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)唆缴,“玉大人,你說(shuō)我怎么就攤上這事黍翎∶婊眨” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 168,561評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵匣掸,是天一觀的道長(zhǎng)趟紊。 經(jīng)常有香客問(wèn)我,道長(zhǎng)碰酝,這世上最難降的妖魔是什么霎匈? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 59,782評(píng)論 1 298
  • 正文 為了忘掉前任,我火速辦了婚禮送爸,結(jié)果婚禮上铛嘱,老公的妹妹穿的比我還像新娘。我一直安慰自己袭厂,他們只是感情好墨吓,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,798評(píng)論 6 397
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著纹磺,像睡著了一般帖烘。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上橄杨,一...
    開(kāi)封第一講書(shū)人閱讀 52,394評(píng)論 1 310
  • 那天秘症,我揣著相機(jī)與錄音照卦,去河邊找鬼。 笑死历极,一個(gè)胖子當(dāng)著我的面吹牛窄瘟,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播趟卸,決...
    沈念sama閱讀 40,952評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼蹄葱,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了锄列?” 一聲冷哼從身側(cè)響起图云,我...
    開(kāi)封第一講書(shū)人閱讀 39,852評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎邻邮,沒(méi)想到半個(gè)月后竣况,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,409評(píng)論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡筒严,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,483評(píng)論 3 341
  • 正文 我和宋清朗相戀三年丹泉,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片鸭蛙。...
    茶點(diǎn)故事閱讀 40,615評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡摹恨,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出娶视,到底是詐尸還是另有隱情晒哄,我是刑警寧澤,帶...
    沈念sama閱讀 36,303評(píng)論 5 350
  • 正文 年R本政府宣布肪获,位于F島的核電站寝凌,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏孝赫。R本人自食惡果不足惜较木,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,979評(píng)論 3 334
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望青柄。 院中可真熱鬧伐债,春花似錦、人聲如沸刹前。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,470評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)喇喉。三九已至祖今,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背千诬。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,571評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工耍目, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人徐绑。 一個(gè)月前我還...
    沈念sama閱讀 49,041評(píng)論 3 377
  • 正文 我出身青樓邪驮,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親傲茄。 傳聞我的和親對(duì)象是個(gè)殘疾皇子毅访,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,630評(píng)論 2 359