1. 程式人生 > >vue API 知識點(1)---全域性 API 總結

vue API 知識點(1)---全域性 API 總結

1.Vue.extend(options)

  構造器,建立一個 子類 。引數是一個包含元件選項的物件

  data 選項是特例,需要注意 在 Vue.extend() 中它必須是一個函式,

  <div id="test"></div>
  // 建立構造器
  let MyTest = Vue.extend({
    template: '<p>{{name}} {{age}}</p>',
    data(){
      return {
        name: 'zhangning',
        age: '24'
      }
    }
  })

  建立 MyTest 例項,並掛載到一個元素上

  new MyTest().$mount('#test')

  最終結果如下

  <p>zhangning 24</p>

  上面 extend 建立的是 Vue 構造器,而不是一個具體的元件例項,所以不能夠通過 new Vue({components: testExtend}) 來直接使用,需要通過 new MyTest().$mount('#test') 來掛載到指定的元素上

  *呼叫 Vue.extend() 建立的是一個元件構造器

  *通常在建立元件構造器時,傳入 template 代表我們自定義元件的模板

  *該模板就是在使用到元件的地方,要顯示的 HTML 程式碼

  *但是,這種寫法在vue2之後幾乎就不再使用了,都是直接使用語法糖,不過我們還是要學習的,為後面的學習打下基礎

  現在我們通常不使用 Vue.extend() 來註冊元件了,使用語法糖的寫法,直接把物件放在 Vue.component() 來註冊元件,可以看第 7 個API進行學習

    呼叫Vue.component() 是將剛才的元件構造器註冊為一個元件,並且給它起一個元件的標籤名字

    所以需要傳遞兩個引數:1.註冊元件的標籤名 2.元件構造器

  元件必須掛在在某個Vue例項下,否則不會生效

  示例:封裝一個全域性提示元件

  首先建立一個 message.vue 元件

  <template>
    <transition>
      <div v-show='show'>{{message}}</div>
    </transition>
  </template>

  <script>
    export default{
      data(){
        return {
          show: false,
          message: ''
        }
      }
    }
  </script>

  <style scoped>
    div {
      padding: 10px;
      color: #ddd;
      background: red;
      text-align: center;
      position: fixed;
      top: 30%;
      left: 50%;
    }   </style>

  然後在 main.js 中配置

  import Message from './components/Message.vue'

  const MessageM = {
    install: function(Vue) {
      // 建立一個 vue 的子類元件
      const MessageConstructor = Vue.extend(Message)
      // 建立子類例項,並掛載到動態建立的元素上,並將元素新增到全域性結構中
      const inst = new MessageConstructor().$mount(document.createElement('div'))
      document.body.appendChild(inst.$el)
      // 在 vue 原型鏈上註冊方法,控制組件
      Vue.prototype.$message = (msg, time = 1000) => {
        inst.message = msg
        inst.show = true
        setTimeout((
          inst.show = false
        ), time)
      }
    }
  }
  Vue.use(MessageM)

  在元件內使用

  this.$message('訊息提示')

  以上就是一個簡單的全域性訊息提示

 

2.Vue.nextTick

  在寫詞DOM更新迴圈結束之後執行延遲迴調。在修改資料之後立即使用這個方法,獲取更新後的DOM

<template>
  <div>
    <div ref='valRef'>{{ val }}</div>
    <div>{{ val1 }}</div>
    <div>{{ val2 }}</div>
    <div>{{ val3 }}</div>
    <el-button type="primary" @click.once='handleClick'>改變val</el-button>
  </div>
</template>

<script>
export default {
  name: 'index',
  data() {
    return {
      val: 'zhangning',
      val1: '',
      val2: '',
      val3: ''
    }
  },
  methods: {
    // 點選按鈕時,val1和val3獲取的是初次載入時候的val的值,因為vue的DOM是非同步載入,
    // 而使用了nextTick的val2的值在msg改變之後,就立刻獲取到了val更新之後的值
    handleClick() {
      this.val = '我已改變';
      // DOM 未更新,獲取不到最新的dom
      this.val1 = this.$refs.valRef.innerHTML;
      this.$nextTick(() => {
        // DOM 已更新,獲取最新的dom
        this.val2 = this.$refs.valRef.innerHTML;
      })
      // DOM 未更新,獲取不到最新的dom
      this.val3 = this.refs.valRef.innerHTML;
    }
  }
}
</script>

  官方給出的解釋和例子(非同步更新佇列)

  Vue 在更新 DOM 時是非同步執行的。只要監聽到資料變化,Vue 將開啟一個佇列,並緩衝在同一事件迴圈中發生的所有資料變更,如果同一個 watcher 被多次觸發,只會被推入到佇列中一次。這種在緩衝時去除重複資料對於避免不必要的計算和 DOM 操作是非常重要的。然而在下一個的事件迴圈 tick 中,Vue 重新整理佇列並執行實際(已去重)工作。Vue 在內部對非同步佇列嘗試使用原生的Promise.then、MutationObserver 和 setImmediate,如果執行環境不支援,則會採用 setTimeout(fn, 0) 代替。

  例如,當設定 vm.someData = 'newVlaue',該元件不會立即重新渲染,當重新整理佇列時,元件會在下一個事件迴圈 tick 中更新。多數情況我們不需要關心這個過程,但是如果想基於更新後的 DOM 狀態做點什麼,這就有點棘手。雖然Vue鼓勵我們使用資料驅動的方式思考,避免直接接觸 DOM ,但是有時我們必須要這麼做。為了在資料變化之後等待 Vue 完成更新 DOM,可以在資料變化之後立即使用 Vue.nextTick(callback)。這樣回撥函式將在 DOM 更新完成之後被呼叫。例如

<div id="example">{{message}}</div>
var vm = new Vue({
  el: '#example',
  data: {
    message: '123'
  }
})
vm.message = 'new message' // 更改資料
vm.$el.textContent === 'new message' // false
Vue.nextTick(function () {
  vm.$el.textContent === 'new message' // true
})

在元件內使用 vm.$nextTick() 例項方法特別方便,因為它不需要全域性 Vue ,並且回撥函式中的 this 將自動繫結到當前的 Vue 例項上

Vue.component('example', {
  template: '<span>{{ message }}</span>',
  data: function () {
    return {
      message: '未更新'
    }
  },
  methods: {
    updateMessage: function () {
      this.message = '已更新'
      console.log(this.$el.textContent) // => '未更新'
      this.$nextTick(function () {
        console.log(this.$el.textContent) // => '已更新'
      })
    }
  }
})

  因為 $nextTick() 返回一個 Promise 物件,所以你可以使用新的語法 async/await 完成相同的事情

methods: {
  updateMessage: async function () {
    this.message = '已更新'
    console.log(this.$el.textContent) // => '未更新'
    await this.$nextTick()
    console.log(this.$el.textContent) // => '已更新'
  }
}

 

3.Vue.set

  Vue.set(target, key, value)

    target:要更改的資料來源(可以是物件或者陣列)

    key:要更改的具體資料

    value:重新賦的值

  由於 js 的限制,Vue 不能檢測出資料的改變,但是通過這種方法修改陣列中的資料,就會檢測到陣列的改變,是響應式的

  用法:向響應式物件中新增一個 property, 並確保這個新 property 同樣是響應式的,且觸發檢視更新。它必須用於向響應式物件上新增新 property,因為 Vue 無法探測普通的新增 property (比如 arr[1] = 110)

export default {
  name: 'index',
  data() {
    return {
      arr: [1,2,3]
    }
  },
  methods: {
    // 修改 arr[1] 變為 200
    handleChange(){
      this.$set(this.arr, 1, 200);// arr: [1, 200, 3]
    },
    // arr 陣列新增元素 600
    handleAddArr(){
      this.$set(this.arr, this.arr.length, 600);
    }
  }
}

 

4.Vue.delete()

  Vue.delete(target, key, value)

    target:要刪除的資料來源(可以是物件或者陣列)

    key:要刪除的具體資料

  用法:刪除物件的 property。如果物件是響應式的,確保刪除能觸發更新檢視。這個方法主要用於避開 Vue 不能檢測到 property 被刪除的限制,雖然很少使用,但直到要會用

export default {
  name: 'index',
  data() {
    return {
      zhangning: {
        height: 187,
        name: 'zhangning',
        sex: '男'
      }
    }
  },
  methods: {
    // 刪除 name
    handleDeleteName() {
      this.$set(this.zhangning, 'name');
    }
  }
}

 

5.Vue.directive()

  Vue.directive(string, Function | Object)

  註冊或獲取全域性指令

  宣告週期:

    bind:只調用一次,指令第一次繫結到元素時呼叫。在這裡可以進行一次性的初始化設定。

    inserted:被繫結元素插入父節點時呼叫(僅保證父節點存在,但不一定被插入文件中)

    update:所在元件的 VNode 更新時呼叫,但是可能發生在其子 VNode 更新之前。指令的值可能發生改變,也可能沒有,但是你可以通過比較更新前後的值來忽略不必要的模板更新(詳細的鉤子函式引數見下)

      componentUpdated:指令所在元件的 VNode 及其子 VNode 全部更新後呼叫

    unbind:只調用一次,指令與元素解綁時呼叫

  鉤子函式引數

    el:指令所繫結的元素,可以用來直接操作 DOM

    binding:一個物件,包含以下 property:

      name:指令名,不包括 v- 字首

      value:指令的繫結值,例如:v-my-directive='1+1'中,繫結值為 2

      oldValue:指令繫結的前一個值,僅在 update 和 componentUpdated 鉤子中可用,無論值是否改變都可用

      expression:字串形式的指令表示式。例如 v-my-directive='1+1' 中,表示式為 ‘1+1’

      arg:傳給指令的引數,可選。例如 v-my-directive: foo 中,引數為 'foo'

      modifiers:一個包含修飾符的物件。例如:v-my-directive.foo.bar 中,修飾符物件為 {foo: true, bar: true}

    vnode:Vue 編譯生成的虛擬節點

    oldVnode:上一個虛擬節點,僅在 update 和 componentUpdated 鉤子中可用

    <div id="hook-arguments-example" v-demo:foo.a.b="message"></div>
    Vue.directive('demo', {
      bind: function (el, binding, vnode) {
        var s = JSON.stringify
        el.innerHTML =
        'name: '       + s(binding.name) + '<br>' +
        'value: '      + s(binding.value) + '<br>' +
        'expression: ' + s(binding.expression) + '<br>' +
        'argument: '   + s(binding.arg) + '<br>' +
        'modifiers: '  + s(binding.modifiers) + '<br>' +
        'vnode keys: ' + Object.keys(vnode).join(', ')
      }
    })

    new Vue({
      el: '#hook-arguments-example',
      data: {
        message: 'hello!'
      }
    })

    頁面展示效果如下

    name: 'demo'
    value: 'hello!'
    expression: 'message'
    argument: 'foo'
    modifiers: {a: true, b: true}
    vnode keys: tag,data,children,text,elm,ns,context...

  動態指令引數,指令的引數可以是動態的,例如,在 v-mydirective:[argument]='value'中,argument 引數可以根據元件資料進行更新,這可以讓我們的自定義指令靈活使用。

  建立一個自定義指令,把元素固定在距離頂部 200px 的位置

  <div id="test">
    <p>Scroll down the page</p>
    <p v-pin="200">距離頂部200px</p>
  </div>
  Vue.directive('pin', {
    bind: function(el, binding, vnode){
      el.style.position = 'fixed'
      el.style.top = binding.value + 'px'
    } 
  })

  new Vue({
    el: '#test' 
  })

  當我們需要固定在左側而不是頂部的時候,這時候我們就需要用到動態指令

  <div id="test">
    <p>Scroll down the page</p>
    <p v-pin:[direction]="200">距離頂部200px</p>
  </div>
  Vue.directive('pin', {
    bind: function(el, binding, vnode){
      el.style.position = 'fixed'
      let s = binding.arg == 'left' ? 'left' : 'top'
      el.style[s] = binding.value + 'px'
    } 
  })

  new Vue({
    el: '#test' ,
    data(){
      return {
        direction: 'left'
      }
    }
  })

    以上這個自定義指令現在的靈活性就足以支援一些不同的用例了

  函式簡寫

    很多時候,我們想在 bind 和 update 時觸發相同行為,而不關心其他的鉤子。

    Vue.directive('pin', function(el, binding){
      el.style.top = binding.value + 'px'
    })

    如果指令需要多個值,可以傳入 js 物件,指令函式能夠接收所有合法的 js 表示式

    <div v-demo="{ color: 'red', text: 'hello'}"></div>
    Vue.directive('demo', function(el, binding){
      console.log(binding.value.color) // red
      console.log(binding.value.text) // hello
    })

  在專案中使用的案例

    通過許可權控制每個頁面的按鈕,

  先定義一個 directive.js,寫上全域性指令 

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

Vue.directive('permission', {
  inserted: (el, binding) => {
    if (store.getters.userButtons.length) {
      const buttons = store.getters.userButtons;
      if (buttons.indexOf(binding.value) < 0) el.parentNode.removeChild(el);
    } else {
      store.dispatch('getInfo').then(data => {
        const { buttons } = data.buttons;
        if (buttons.indexOf(binding.value) < 0) el.parentNode.removeChild(el);
      });
    }
  }
});

  在 main.js 中全域性引入

import './directive.js'

  在 vue 元件中使用,判斷有沒有下載按鈕許可權

    <el-button
          round
          icon="el-icon-document"
          type="primary"
          v-permission="'SJML_SQXZ'"
          @click="applyForDownload"
    >下載文件</el-button>

 

6.Vue.filter()

  定義過濾器,可被用於常見的文字格式化。過濾器可以用在兩個地方:雙花括號插值和 v-bind 表示式,過濾器應該被新增在 js 表示式的尾部,由管道符號指示:'|'

  <!-- 在雙花括號中 -->
  {{ message | capitalize }}
  <!-- 在 `v-bind` 中 -->   <div v-bind:id="rawId | formatId"></div>

  在一個元件的選項中定義本地過濾器

  filters: {
    capitalize: function (value) {
      if (!value) return ''
      value = value.toString()
      return value.charAt(0).toUpperCase() + value.slice(1)
    }
  }

  在建立 Vue 例項之前全域性定義過濾器

  Vue.filter('capitalize', function() {
    if (!value) return ''
    value = value.toString()
    return value.charAt(0).toUpperCase() + value.slice(1)
  })
  new Vue({
    // ...
  })

  注意:當全域性過濾器和區域性過濾器重名時,會採用區域性過濾器

  過濾器函式總接收表示式的值作為第一個引數

  過濾器可以串聯:

    {{ message | filterA | filterB }}

  這個例子中,filterA 被定義為接收單個引數的過濾器函式,表示式 message 的值將作為引數傳入到函式中。然後繼續呼叫同樣被定義為接收單個引數的過濾器函式 filterB,將 filterA 的結果傳遞給 filterB 中。

  過濾器時 js 函式,因此可以接收引數

    {{ message | filterA('arg1', arg2) }}

  這個例子,filterA 被定義為接收三個引數的過濾器函式,其中 message 的值作為第一個引數,普通字串 'arg1' 作為第二個引數, arg2 作為第三個引數

  在專案中使用的案例

  先定義一個 filters.js 

export { formatBoolean, formatDate, formatNum, formatStatus };

// 布林值
function formatBoolean(value) {
  return value ? "是" : "否";
}

// 狀態
function formatStatus(value) {
  return value ? "成功" : "失敗";
}
// 時間戳轉換
function formatDate(value) {
  let date = new Date(parseInt(value));
  let Y = date.getFullYear();
  let M =
    date.getMonth() + 1 < 10
      ? "0" + (date.getMonth() + 1)
      : date.getMonth() + 1;
  // let D = date.getDate();
  let D = date.getDate() < 10 ? "0" + date.getDate() : date.getDate();
  let h = date.getHours() < 10 ? "0" + date.getHours() : date.getHours();
  let m = date.getMinutes() < 10 ? "0" + date.getMinutes() : date.getMinutes();
  let s = date.getSeconds() < 10 ? "0" + date.getSeconds() : date.getSeconds();
  return Y + "." + M + "." + D + " " + h + ":" + m + ":" + s;
}

// 數值加逗號
function formatNum(num) {
  num = (num || 0).toString();
  let result = "";
  while (num.length > 3) {
    result = "," + num.slice(-3) + result;
    num = num.slice(0, num.length - 3);
  }
  if (num) {
    result = num + result;
  }
  return result;
}

  然後在 main.js 中進行全域性引入

  import * as filters from './filters.js'
  Object.keys(filters).forEach(item => {
    Vue.filter(item, filters[item])
  })
  // 這裡講一下 Object.keys() 方法,表示給定物件的所有可列舉屬性的字串陣列   let zn = {name: 'zhangning', age: '24', height: '187'}   Object.keys(zn);// ['name', 'age', 'height'] 返回可列舉屬性組成的陣列   // 處理陣列,返回索引值陣列   let arr = [100, 200, 300, 400, 500]   Object.keys(arr);// ['0', '1', '2', '3', '4'] 返回索引值字串組成的陣列   // 處理字串,返回索引值陣列   let str = 'zhang';   Object.keys(str);// ['0', '1', '2', '3', '4']   // 常用技巧   let zn = {name: 'zhangning', age: '25', address: '合肥', getName: function()}   Object.keys(person).map(item => {     person[item] // 獲取到屬性對應的值,做一些處理   })

 

7.Vue.component()

  // 定義一個名為 button-counter 的新元件
  Vue.component('button-counter', {
    data: function () {
      return {
        count: 0
      }
    },
    template: '<button v-on:click="count++">You clicked me {{ count }} times.</button>'
  })

  data 必須是一個函式,因此每個例項可以維護一份被返回物件的獨立的拷貝,如果不是一個函式,就會影響到元件所有例項

  在專案中自定義全域性元件案例

  首先建立一個元件 download.vue

  然後建立一個 download.js,在 js 中引入元件

  // 引入元件
  import DLFLoading from './index.vue';
  // 自定義元件物件
  const DownloadDialog = {
    // install 是預設的方法。當外界在 use 這個元件的時候,就會呼叫本身的 install 方法,同時傳一個 Vue 這個類的引數
    install: function(Vue) {
      // Vue.component() 與正常的全域性註冊元件用法相同,可以理解為通過 install 和 Vue.use()函式註冊了全域性元件
      Vue.component('DownloadDialog', DLFLoading);
    }
  }
  // 匯出
  export default DownloadDialog;

  接著在 main.js 中全域性引入元件

  // 全域性引入自定義下載 loading
  import DownloadDialog from '@/components/DownloadDialog/download.js';
  Vue.use(DownloadDialog);

  最後在專案中直接就可以使用

  <DownloadDialog
      @cancelDownload="cancelDownload"
      :downloadOver="downloadOver"
      :downloadLoading="downloadLoading"
    ></DownloadDialog>

 

8.Vue.use()

  安裝 Vue.js 外掛。如果外掛是一個物件,必須提供 install 方法。如果外掛是一個函式,它會被作為 install 方法。install 方法呼叫時,會將 Vue 作為引數傳入。

  該方法需要在 new Vue() 之前被呼叫

  當 install 方法被同一個外掛多次呼叫,外掛將只會被安裝一次。

  外掛通常用來為 Vue 新增全域性功能。外掛的功能範圍沒有嚴格的限制 一般有以下幾種

    1.新增全域性方法或者property

    2.新增全域性資源:指令/過濾器/過渡等

    3.通過全域性混入來新增一些元件選項

    4.新增 Vue 例項方法,通過把他們新增到 Vue.prototype 上實現

    5.一個庫,提供自己的 api,同時提供上面提到的一個或多個功能

  使用外掛

    通過全域性方法 Vue.use() 使用外掛。它需要在你呼叫 new Vue() 啟動應用之前完成

    // 呼叫 MyPlugin.install(Vue)
    Vue.use(MyPlugin)
    new Vue({

      // ...元件選項
    })

 

    也可以傳入一個可選的選項物件

   Vue.use(MyPlugin, {someOption: true})

    Vue.use 會自動阻止多次註冊相同外掛,即使多次呼叫也只會註冊一次該外掛

 

9.Vue.mixin()

  全域性註冊一個混入,影響註冊之後所有建立的每個 Vue 例項。外掛作者可以使用混入,向元件注入自定義的行為(官方不推薦使用)

  官網全域性混入案例。混入也可以進行全域性註冊,使用時格外小心,一旦使用全域性混入,它將影響每一個之後建立的 Vue 例項。使用恰當時,它可以用來自定義選項注入處理邏輯。

  // 為自定義的選項 myOption 注入一個處理器

  Vue.mixin({
    created: function(){
      var myOption = this.$options.myOption
      if(myOption) {
        console.log(myOption)
      }
    }
  })

  new Vue({
    myOption: 'zhangning'
  })
  // => 'zhangning'

  注意:要謹慎使用全域性混入,因為它影響每個單獨建立的 Vue 例項(包括第三方元件)。大多數情況下,之應當應用於自定義選項,就像上面例項一樣,推薦將其作為外掛釋出,以避免重複應用混入

  使用案例

  定義一個 mixin.js

  let MiXin = {
    data(){
      return {
        name: 'zhangning'
      }
    },
    created(){
      console.log('這是mixin中的name', this.name)
    },
    mounted(){},
    methods: {}
  }
  export default MiXin
  // 全域性引入

  import mixin from './mixin'
  Vue.mixin(mixin)

  // 在 vue 元件中區域性引入
  import '@/mixin'
  export default {
    mixins: [mixin]
  }

  混入和元件的合併注意事項

  1.資料物件 data 在內部進行遞迴合併,在和元件的資料發生衝突時以元件資料優先

  2.同名鉤子函式(created,mounted)將混合為一個數組,都將被呼叫。另外混入物件的鉤子將在元件自身鉤子之前呼叫

  3.值為物件的選項(methods,components,directives)將被混合為同一個物件,兩個物件鍵名衝突時,去元件物件的鍵值對

 

10.Vue.compile() -- 模板渲染

  將一個模板字串編譯成 render 函式。旨在完整版時可用

  let res = Vue.compile('<div><span>{{ massage }}</span></div>')

  new Vue({

    data: {

      message: 'hello'

    },

    render: res.render,

    staticRenderFns: res.staticRenderFns

  })

  以上是官網給的一個小例項。

  以後深入理解之後,再回來更新

 

11.Vue.observable() -- 可用於元件間共享資料

  讓一個物件可響應,Vue 內部會用它來處理 data 函式返回的物件。

  返回的物件可以直接用於渲染函式和計算屬性內,並且會在發生變更時出發相應的更新。

  處理簡單的跨元件共享資料狀態的問題,可以說是個精簡的 vuex

  示例

  建立store.js

  import Vue from 'vue'
  export const store = Vue.observable({num: 0})
  export const mutations = {
    setNum (num) {
      store.num = num
    }
  }

  在元件中使用(所有的說明都沒有舉例子來的實在,理解的更快)

  <template>
    <div>
      <span>選擇數量</span>
      <button @click="setNum(num + 1)"> + </button>
      <span>count</span>
      <button @click="setNum(num - 1)"> - </button>
    </div>
  </template>

  <script>
    import { store, mutations } from '@/store/store' 
    export default {
      name: 'numIndex',
      computed: {
        count() {
          return store.num
        }
      },
      methods: {
        setNum: mutations.setNum
      }
    }
  </script>

 

12.Vue.version()

  提供字串形式的 Vue 安裝版本號。這對社群的外掛和元件來說非常有用,你可以根據不同的版本號採取不同的策略

  let version = Number(Vue.version.split('.')[0])

  if (version == 2) {

  } else if (version == 1) {

  } else {}

  就是獲取當前使用的 vue 版本號,原理就是讀取 package.json 中的 version 欄位

 

  以上就是 vue API 全域性 API 的所有內容,

  寶劍鋒從磨礪出,梅花香自苦寒