1. 程式人生 > >vue構造函數(根實例化時和組件實例對象選項)參數:選項詳解

vue構造函數(根實例化時和組件實例對象選項)參數:選項詳解

pla run nbsp 祖先 使用場景 函數 eat 簡單 ejs

實例選項(即傳給構造函數的options):數據,DOM,生命周期鉤子函數,資源,組合,其他

數據

data

屬性能夠響應數據變化,當這些數據改變時,視圖會進行重渲染。

訪問方式:

1、通過 vm.$data 訪問。

var data = { a: 1 }
var vm = new Vue({
  el: ‘#example‘,
  data: data
})

vm.$data === data// => true
vm.$el === document.getElementById(‘example‘) // => true

2、Vue 實例代理(以 _

$ 開頭的屬性 不會 被 Vue 實例代理)了 data 對象上所有的屬性。

// 我們的數據對象
var data = { a: 1 }

// 該對象被加入到一個 Vue 實例中
var vm = new Vue({
  data: data
})

// 獲得這個實例上的屬性
// 返回源數據中對應的字段
vm.a == data.a // => true

在組件中:

1、data 必須為返回一個初始數據對象的函數,因為組件可能被用來創建多個實例。如果 data 仍然是一個純粹的對象,則所有的實例將共享引用同一個數據對象!通過函數的return,每次返回的是不同的對象。

2、每次創建一個新實例後,調用 data 函數會返回初始數據的一個全新副本數據對象。

拷貝原始數據對象:

vm.$data 傳入 JSON.parse(JSON.stringify(...)) 得到深拷貝的原始數據對象。

註意:

1、data作為函數時如果使用了箭頭函數,則 this 不會指向這個組件的實例,函數的第一個參數將是實例。

data: vm => ({ a: vm.myProp })

2、只有當實例被創建時 data 中存在的屬性才是響應式的。

3、使用Object.freeze()對data對象屬性凍結,data不再是響應式。

使用建議:

1、推薦在創建實例之前,就聲明所有的根級響應式屬性。

2、後續才需要的某個屬性,但是一開始它為空或不存,設置一些初始值,保證它是響應式的。

props

可以是數組或對象,用於接收來自父組件的數據,定義了當前組件有哪些可配置的屬性。

當一個值傳遞給一個 prop 特性的時候,它就變成了那個組件實例的一個屬性。

<script>
  var obj = {
    props:{
      parentDataA:Number
    },
    mounted(){
      console.log(this.parentDataA);
    }
  };
    export default obj;
</script>

使用建議:

(1)寫通用組件時,props最好用對象的寫法,針對每個屬性設置類型、默認值或自定義校驗屬性的值,是組件比較嚴謹。當 prop 驗證失敗的時候,(開發環境構建版本的) Vue 將會產生一個控制臺的警告。

//類型檢測String、Number、Boolean、Array、Object、Date、Function、Symbol
Vue.component(‘my-component‘, {
  props: {
        propA: Number,// 基礎的類型檢查 (`null` 和 `undefined` 會通過任何類型驗證)
        propB: [String, Number], // 多個可能的類型
        propC: {// 必填的字符串
              type: String,
              required: true
        },
         propD: { // 帶有默認值的數字
              type: Number,
              default: 100
        },    
        propE: {// 帶有默認值的對象
              type: Object,
              default: function () {// 對象或數組默認值必須從一個工廠函數獲取
                return { message: ‘hello‘ }
              }
        },
        propF: { // 自定義驗證函數
              validator: function (value) {
              // 這個值必須匹配下列字符串中的一個
              return [‘success‘, ‘warning‘, ‘danger‘].indexOf(value) !== -1
      }
    }
  }
})                            

(2)在dom中,使用短橫線分隔命名,在js中使用時是駝峰命名。

(3)是單向數據流,不應該在子組件中更改prop,會報錯。可以在data中定義或者在computed中定義對應的屬性。註意:對於一個數組或對象類型的 prop 來說,在子組件中改變這個對象或數組本身將會影響到父組件的狀態。

4)prop 會在一個組件實例創建之前進行驗證,所以實例的屬性 (如 datacomputed 等) 在 defaultvalidator 函數中是不可用的。

propsData

只用於 new 的實例中,用在全局擴展(extend)時進行傳遞數據。在實例化extend的構造器時,傳入屬性必須是propsData、而不是props哦。實例中props接收propsData,把props的數據作為測試數據。

不推薦用全局擴展的方式作自定義標簽,完全可以使用組件來做,propsData在實際開發中我們使用的並不多。另外的例子,可以見全局API中的extend部分。

var Comp = Vue.extend({
  props: [‘msg‘],
  template: ‘<div>{{ msg }}</div>‘
})

var vm = new Comp({
  propsData: {
    msg: ‘hello‘
  }
})

computed

計算實例的屬性,this 上下文自動地綁定為 Vue 實例。箭頭函數this不會指向實例,需要顯示傳入vm。

computed: {
  aDouble: vm => vm.a * 2
}

計算屬性的結果會被緩存,除非依賴的響應式屬性變化才會重新計算。

var vm = new Vue({
  data: { a: 1 },
  computed: {
    // 僅讀取
    aDouble: function () {
      return this.a * 2
    },
    // 讀取和設置
    aPlus: {
      get: function () {
        return this.a + 1
      },
      set: function (v) {
        this.a = v - 1
      }
    }
  }
})

計算屬性默認只有 getter ,想改變實例屬性,可以提供一個 setter。在getter中改變實例屬性,eslint開啟的情況下會報錯。

使用建議:

1、在get中,不要改變實例屬性,而是通過set來改變。

2、計算屬性依賴響應式屬性,註意它的使用場合和methods以及watch區分。

methods

可通過實例訪問這些方法或在指令表達式或在模板插值中使用。方法中的 this 自動綁定為 Vue 實例。

註意,不應該使用箭頭函數來定義 method 函數this 不會指向 Vue 實例。

常用姿勢:

methods: {
    greet: function (event) {
      // `this` 在方法裏指向當前 Vue 實例
      alert(‘Hello ‘ + this.name + ‘!‘)
      // `event` 是原生 DOM 事件
      if (event) {
        alert(event.target.tagName)
      }
    },
   say(str,event){
     //...
    },
    console(){
    //...
    }
  }
//直接調用或者傳參調用,都有event傳入
<button v-on:click="greet">Greet</button> 
<button v-on:click="greet($event)">Greet</button> 

//多個參數時,event事件要顯示傳入
<button v-on:click="say(‘what‘,$event)">Say what</button>

//由實例代理,直接被調用
vm.console()//

事件修飾符

使用修飾符時,順序很重要;相應的代碼會以同樣的順序產生。

因此,用 v-on:click.prevent.self 會阻止所有的點擊,而 v-on:click.self.prevent 只會阻止對元素自身的點擊。

<!-- 阻止單擊事件繼續傳播 -->
<a v-on:click.stop="doThis"></a>
<!-- 提交事件不再重載頁面 -->
<form v-on:submit.prevent="onSubmit"></form>
<!-- 修飾符可以串聯 -->
<a v-on:click.stop.prevent="doThat"></a>
<!-- 只有修飾符 -->
<form v-on:submit.prevent></form>
<!-- 添加事件監聽器時使用事件捕獲模式 -->
<!-- 即元素自身觸發的事件先在此處理,然後才交由內部元素進行處理 -->
<div v-on:click.capture="doThis">...</div>
<!-- 只當在 event.target 是當前元素自身時觸發處理函數 -->
<!-- 即事件不是從內部元素觸發的 -->
<div v-on:click.self="doThat">...</div>
<!--2.1.4 新增 點擊事件將只會觸發一次 ,還能被用到自定義的組件事件上-->
<a v-on:click.once="doThis"></a>

<!-- 滾動事件的默認行為 (即滾動行為) 將會立即觸發 -->
<!-- 而不會等待 `onScroll` 完成  -->
<!-- 這其中包含 `event.preventDefault()` 的情況 -->
<!--這個 .passive 修飾符尤其能夠提升移動端的性能 -->
<!--不要把 .passive 和 .prevent 一起使用-->
<div v-on:scroll.passive="onScroll">...</div>

使用建議:

一般使用在事件上面,大部分時候可以使用computed代替methods和watch。

watch

key為要觀察的表達式,值為對應的回調函數,當表達式的值改變,就觸發回調。

回調函數可以是方法名(字符串形式),方法,或者包含配置選項的對象。

註意:Vue 實例將會在實例化時調用 $watch(),遍歷 watch 對象的每一個屬性,此時要是設置了immediate為true,其handle會立即被調用。

watch: {
    a: function (val, oldVal) {
      console.log(‘new: %s, old: %s‘, val, oldVal)
    },
       b: ‘someMethod‘, // 方法名
       c: {
      handler: function (val, oldVal) { /* ... */ },
      deep: true // 深度 watcher,當監聽的是一個對象的時候,指定deep: true可監聽對象內部值的變化

    },
       d: {
      handler: function (val, oldVal) { /* ... */ },
      immediate: true // 該回調將會在偵聽開始之後立即以表達式的當前值觸發回調
    },
    e: [
      ‘handle1‘,
      function handle2 (val, oldVal) { /* ... */ },
      {
        handler: function handle3 (val, oldVal) { /* ... */ },
        /* ... */
      }
    ],
    // watch vm.e.f‘s value: {g: 5}
    ‘e.f‘: function (val, oldVal) { /* ... */ }
  }

更復雜的表達式可以使用vm.$watch處理,用一個函數取代,回調函數參數為新值和舊值。

(在變異 (不是替換) 對象或數組時,舊值與新值相同,指向同一個引用)

// 函數
vm.$watch(
  function () {
    // 表達式 `this.a + this.b` 每次得出一個不同的結果時
    // 處理函數都會被調用。
    // 這就像監聽一個未被定義的計算屬性
    return this.a + this.b
  },
  function (newVal, oldVal) {
    // 做點什麽
  }
)

vm.$watch 返回一個取消觀察函數,用來停止觸發回調:

var unwatch = vm.$watch(‘a‘, cb)
// 之後取消觀察
unwatch()

computed,methods,watch的使用場景

1、大部分時候都使用computed

 data: {
    firstName: ‘Foo‘,
    lastName: ‘Bar‘,
    fullName: ‘Foo Bar‘
  }

computed: {
  fullName: {
    // getter
    get: function () {
      return this.firstName + ‘ ‘ + this.lastName
    },
    // setter
    set: function (newValue) {
      var names = newValue.split(‘ ‘)
      this.firstName = names[0]
      this.lastName = names[names.length - 1]
    }
  }
}

2、一般在事件裏調用methods

3、當需要在數據變化時執行異步或開銷較大的操作時,使用watch。

Dom

el

只在 new 實例時傳入,不在組件中使用。值為頁面上已存在的 DOM 元素,作為 Vue 實例的掛載目標。

可以是 CSS 選擇器,也可以是一個 HTMLElement 實例。

template

字符串模板

如果值以 # 開始,則它將被用作選擇符,並使用匹配元素的 innerHTML 作為模板。

<template id="myComponent">
            <div>This is a component!</div>
</template>
  Vue.component(‘my-component‘,{
            template: ‘#myComponent‘
  })

如果為標簽字符串,模板將會 替換 掛載的元素。掛載元素的內容都將被忽略,除非模板的內容有分發插槽。

new Vue({
el: ‘#app‘,
components:{App},
template: ‘<App/>‘
})

這裏面涉及到一個簡寫的處理,如果你不在組件上面添加屬性或者指令的話,你就可以寫成單標簽的形式 <App/>其實就是 ‘ <App><App/>’

el: ‘#app‘ 是index.html 的<div id="app"></div>

App.vue 的<div id="app">xxxxxxxx</div> 會替換index中的<div id="app"></div> 。

components 是聲明有哪些組件,可以放多個組件對象,比如:components:{App,App2,App3}

template 是使用哪個組件,如果想用App2,則需要設置template: ‘<App2/>‘。

render函數

字符串模板(template)的代替方案,多用於動態生成dom的場景,允許你發揮 JavaScript 最大的編程能力。

createElement 方法作為第一個參數用來創建 VNode

比如:某個組件,通過level這個prop來控制模板裏內容的生成

<anchored-heading :level="1">Hello world!</anchored-heading>

使用template寫法:

<script type="text/x-template" id="anchored-heading-template">
  <h1 v-if="level === 1">
    <slot></slot>
  </h1>
  <h2 v-else-if="level === 2">
    <slot></slot>
  </h2>
  <h3 v-else-if="level === 3">
    <slot></slot>
  </h3>
......4,5,6...
</script>

使用render:

Vue.component(‘anchored-heading‘, {
  render: function (createElement) {
    return createElement(
      ‘h‘ + this.level,   // 標簽名稱
      this.$slots.default // 子元素數組
    )
  },
  props: {
    level: {
      type: Number,
      required: true
    }
  }
})

vm.$slots查閱博文:slot。

createElement函數(可以理解為document.createElement,只是參數不同而已),用於生成“虛擬節點 (Virtual Node)”,也常簡寫它為“VNode”。

函數接收三個參數:
參數一: {String | Object | Function}, HTML 標簽字符串,組件選項對象,或者解析上述任何一種的一個 async 異步函數。必需參數。
參數二:包含模板相關屬性的數據對象
可以在 template 中使用這些特性。可選參數。
參數三:{String | Array},子虛擬節點 (VNodes),也可以使用字符串來生成“文本虛擬節點”。可選參數。

[
    ‘先寫一些文字‘,
    createElement(‘h1‘, ‘一則頭條‘),
    createElement(MyComponent, {
      props: {
        someProp: ‘foobar‘
      }
    })
  ]

使用render的常用姿勢:

1、除了代替上面的v-if和v-for功能(即不要把渲染邏輯寫在模板裏)

<ul v-if="items.length">
  <li v-for="item in items">{{ item.name }}</li>
</ul>
<p v-else>No items found.</p>

//使用render
props: [‘items‘],
render: function (createElement) {
  if (this.items.length) {
    return createElement(‘ul‘, this.items.map(function (item) {
      return createElement(‘li‘, item.name)
    }))
  } else {
    return createElement(‘p‘, ‘No items found.‘)
  }
}

2、還能通過數據對象實現v-model:

props: [‘value‘],
render: function (createElement) {
  var self = this
  return createElement(‘input‘, {
    domProps: {
      value: self.value
    },
    on: {
      input: function (event) {
        self.$emit(‘input‘, event.target.value)
      }
    }
  })
}

3、使用render 函數渲染多次重復的元素/組件 。下例渲染了 20 個相同的段落:

render: function (createElement) {
  return createElement(‘div‘,
    Array.apply(null, { length: 20 }).map(function () {
      return createElement(‘p‘, ‘hi‘)
    })
  )
}

renderError函數

只在開發者環境下工作,當 render 函數遭遇錯誤時,其錯誤將會作為renderError函數的第二個參數。這個功能配合 hot-reload 非常實用。

new Vue({
  render (h) {
    throw new Error(‘oops‘)
  },
  renderError (h, err) {
    return h(‘pre‘, { style: { color: ‘red‘ }}, err.stack)
  }
}).$mount(‘#app‘)

生命周期鉤子函數

一共十一個函數。

一般實例裏有的生命周期鉤子函數:beforeCreate,created,beforeMount,mounted,beforeUpdate,updated,beforeDestroy,destroyed,errorCaptured

beforecreated:el 和 data (即實例的屬性)並未初始化
created:完成了 data 等屬性的初始化(數據觀測 (data observer),屬性和方法的運算,watch/event 事件回調),el沒有。
beforeMount:完成了 el 和 data 初始化 ,相關的 render 函數首次被調用。
mounted :完成掛載,把值渲染進el裏。

註意 mounted 不會承諾所有的子組件也都一起被掛載。如果你希望等到整個視圖都渲染完畢,可以用 vm.$nextTick 替換掉 mounted

mounted: function () {
  this.$nextTick(function () {
    // Code that will run only after the
    // entire view has been rendered
  })
}

beforeUpdate:指view層的數據變化前,不是data中的數據改變前觸發。適合在更新之前訪問現有的 DOM,比如手動移除已添加的事件監聽器。

updated:組件 DOM 已經更新,可以執行依賴於 DOM 的操作。如果要相應狀態改變,通常使用計算屬性或 watcher 取代updated。

destroyed:Vue 實例銷毀後調用。可以這麽理解,執行了destroy操作,後續就不再受vue控制了。

errorCaptured:當捕獲一個來自子孫組件的錯誤時被調用。

activated與deactivated:

在被keep-alive包含的組件/路由中,會多出兩個生命周期的鉤子: activated 與 deactivated。

activated在組件第一次渲染時會被調用,之後在每次緩存組件被激活時調用。

使用了keep-alive就不會調用beforeDestroy(組件銷毀前鉤子)和destroyed(組件銷毀),因為組件沒被銷毀,被緩存起來了,再次進入緩存路由/組件時,不會觸發這些鉤子:

beforeCreate ,created ,beforeMount, mounted

生命周期鉤子註意的點:

1、ajax請求最好放在created裏面,因為此時已經可以訪問this了,請求到數據就可以直接放在data裏面。
2、關於dom的操作要放在mounted裏面,在mounted前面訪問dom會是undefined。
3、每次進入/離開組件都要做一些事情,用什麽鉤子:

(1)不緩存:
進入的時候可以用created和mounted鉤子,離開的時候用beforeDestory和destroyed鉤子,beforeDestory可以訪問this,destroyed不可以訪問this。 (2)緩存了組件:
緩存了組件之後,再次進入組件不會觸發beforeCreate、created 、beforeMount、 mounted,如果你想每次進入組件都做一些事情的話,你可以放在activated進入緩存組件的鉤子中。
同理:離開緩存組件的時候,beforeDestroy和destroyed並不會觸發,可以使用deactivated離開緩存組件的鉤子來代替。


將路由導航、keep-alive、和組件生命周期鉤子結合起來的觸發順序:

假設是從a組件離開,第一次進入b組件:

1- beforeRouteLeave:路由組件的組件離開路由前鉤子,可取消路由離開。 2- beforeEach: 路由全局前置守衛,可用於登錄驗證、全局路由loading等。 3- beforeEnter: 路由獨享守衛 4- beforeRouteEnter: 路由組件的組件進入路由前鉤子。 5- beforeResolve:路由全局解析守衛 6- afterEach:路由全局後置鉤子 7- beforeCreate:組件生命周期,不能訪問this。 8- created:組件生命周期,可以訪問this,不能訪問dom。 9- beforeMount:組件生命周期 10- deactivated: 離開緩存組件a,或者觸發a的beforeDestroy和destroyed組件銷毀鉤子。 11- mounted:訪問/操作dom。 12- activated:進入緩存組件,進入a的嵌套子組件(如果有的話)。 13- 執行beforeRouteEnter回調函數next。

資源

directives函數自定義指令

分為全局和局部自定義指令:

//全局
// 註冊一個全局自定義指令 `v-focus`
Vue.directive(‘focus‘, {
  // 當被綁定的元素插入到 DOM 中時……
  inserted: function (el) {
    // 聚焦元素
    el.focus()
  }
})

//局部,組件中定義一個 directives 的選項
directives: {
  focus: {// 指令的定義
        inserted: function (el) {//指令的鉤子函數
      el.focus()
    }
  }
}

自定義指令對象(比如focus這個對象)的鉤子函數:

bind:只調用一次,指令第一次綁定到元素時調用。在這裏可以進行一次性的初始化設置。

inserted:被綁定元素插入父節點時調用 (僅保證父節點存在,但不一定已被插入文檔中)。

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

componentUpdated:指令所在組件的 VNode 及其子 VNode 全部更新後調用。

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

鉤子函數參數: el、bindingvnodeoldVnode。

el:指令所綁定的元素,可以用來直接操作 DOM 。

binding:對象,有以下屬性:

  • name:指令名,不包括 v- 前綴。
  • value:指令的綁定值,例如:v-my-directive="1 + 1" 中,綁定值為 2
  • oldValue:指令綁定的前一個值,僅在 updatecomponentUpdated 鉤子中可用。無論值是否改變都可用。
  • 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 編譯生成的虛擬節點。移步 VNode API 來了解更多詳情。

oldVnode:上一個虛擬節點,僅在 updatecomponentUpdated 鉤子中可用。

鉤子函數簡寫:

bindupdate 時觸發相同行為,而不關心其它的鉤子,directive第二個參數是函數而不是對象。

Vue.directive(‘color-swatch‘, function (el, binding) {
  el.style.backgroundColor = binding.value
})

指令函數能夠接受所有合法的 JavaScript 表達式,比如binding.value可以是一個對象字面量:

<div v-demo="{ color: ‘white‘, text: ‘hello!‘ }"></div>

Vue.directive(‘demo‘, function (el, binding) {
  console.log(binding.value.color) // => "white"
  console.log(binding.value.text)  // => "hello!"
})

使用姿勢:

註冊局部指令比較多,一般在組件中用來初始化dom。

filters過濾器

分為全局和局部過濾器。

使用場景:用於一些常見的文本格式化(日期格式化,字符轉換,金額處理,input輸入處理等)

註意:

1、過濾器內是沒有this引用的,過濾器內的this是undefined,所以不要在過濾器內嘗試使用this引用組件實例的變量或者方法。

2、過濾器函數始終以表達式的值作為第一個參數。帶引號的參數視為字符串,而不帶引號的參數按表達式計算。

3、可以設置兩個過濾器參數,前提是這兩個過濾器處理的不沖突

4、全局定義過濾器,在創建 Vue 實例之前

5、直接註冊在Vue全局上面,其他不用這個過濾器的實例也會被迫接受,所以要註意區分哪些註冊在全局,哪些註冊為局部

用法:雙花括號插值和 v-bind 表達式 (後者從 2.1.0+ 開始支持),被添加在 JavaScript 表達式的尾部,由“管道”符號指示:

<!-- 在雙花括號中,capitalize過濾器函數將會收到 message 的值作為第一個參數-->
{{ message | capitalize }}

<!-- 在 `v-bind` 中 -->
<div v-bind:id="rawId | formatId"></div>

<!-- 過濾器可以串聯 ,filterA 的結果傳遞到 filterB-->

{{ message | filterA | filterB }}

<!-- 過濾器是 JavaScript 函數,因此可以接收參數,message 的值作為第一個參數,普通字符串 ‘arg1‘ 作為第二個參數,表達式 arg2 的值作為第三個參數。-->
{{ message | filterA(‘arg1‘, arg2) }}

局部(本地)過濾器:在一個組件的選項中定義本地的過濾器

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

在創建 Vue 實例之前全局定義過濾器:

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

new Vue({
  // ...
})

用戶從input輸入的數據在回傳到model之前也可以先處理

<input type="text" v-model="message | change"> <!--用戶從input輸入的數據在回傳到model之前也可以先處理-->

 Vue.filter("change", {
                read: function (value) { // model -> view 在更新 `<input>` 元素之前格式化值
                    return value;
                },
                write: function (newVal,oldVal) { // view -> model  在寫回數據之前格式化值
                    console.log("newVal:"+newVal); 
                    console.log("oldVal:"+oldVal);
                    return newVal;
                }
            });

            var myVue = new Vue({
                el: ".test",
                data: {
                    message:12
                }
            });

components組件列表

頁面需要用到的組件列表,書寫形式如下。

//引入組件
import HelloWorld from "./components/HelloWorld";
//在頁面實例註入組件
 components: {
    HelloWorld
  },
//在頁面使用組件
<HelloWorld />
或者
<HelloWorld><HelloWorld />

參考博文:vue學習之組件

$slots

查閱博文slot。

組合

parent指定父實例

值為父實例實例。parent指定實例的父實例,子實例可以用 this.$parent 訪問父實例,子實例被推入父實例的 $children 數組中。

mixins

分為全局混入和局部混入。

值為成員是對象的數組,對象的key可以是任意的實例選項。可在多組件中復用某些功能。

// 定義一個混入對象
var myMixin = {
  created: function () {
    this.hello()
  },
  methods: {
    hello: function () {
      console.log(‘hello from mixin!‘)
    }
  }
}

// 定義一個使用混入對象的組件
var Component = Vue.extend({
  mixins: [myMixin]
})

var component = new Component() // => "hello from mixin!"

當組件和混入對象含有同名選項時,不同選項的混合規則:

(1)data

先與data的屬性合並,發生沖突時以組件數據優先。

(2)生命周期鉤子函數

將混合為一個數組,都將被調用,混入對象的鉤子將在組件自身鉤子之前調用。

(3)值為對象類型的選項,如methods, components 和directives

混合為同一個對象。兩個對象鍵名沖突時,取組件對象的鍵值對。

全局註冊混入對象:

// 為自定義的選項 ‘myOption‘ 註入一個處理器。
Vue.mixin({
  created: function () {
    var myOption = this.$options.myOption
    if (myOption) {
      console.log(myOption)
    }
  }
})

new Vue({
  myOption: ‘hello!‘
})
// => "hello!"

註意使用! 一旦使用全局混入對象,將會影響到之後創建的所有 Vue 實例(包括第三方模板)。使用恰當時,可以為自定義對象註入處理邏輯。大多數情況下,只應當應用於自定義選項,就像上面示例一樣。也可以將其用作 Plugins 以避免產生重復應用

extends

mixins 類似,用於擴展(混合)實例,區別大概就在於它是一個對象,mixins是個數組

let baseOptions= {
    created(){
        console.log(‘onCreated-1‘);
    }
};

new Vue({
    extends: baseOptions,
    created(){
        //do something
        console.log(‘onCreated-2‘);
    }
    //其他自定義邏輯
});
// -> onCreated-1
// -> onCreated-2

provide/inject

這對選項需要一起使用,允許一個祖先組件向其所有子孫後代註入一個依賴,不論組件層次有多深,並在起上下遊關系成立的時間裏始終生效。

主要為高階插件/組件庫提供用例。並不推薦直接用於應用程序代碼中。

provide 和 inject 綁定並不是可響應的,如果傳入了一個可監聽的對象,那麽其對象的屬性還是可響應的。

provide 選項:一個對象或返回一個對象的函數,指定想要提供給後代組件的數據/方法。

inject 選項:在任何後代組件裏,使用 inject 選項來接收想要添加在這個實例上的屬性。

inject 選項值:

  • 一個字符串數組
  • 一個對象,對象的 key 是本地的綁定名,value 是:
    • 在可用的註入內容中搜索用的 key (字符串或 Symbol),或
    • 一個對象,該對象的:
      • from 屬性是在可用的註入內容中搜索用的 key (字符串或 Symbol)
      • default 屬性是降級情況下使用的 value

使用場景:

  • 祖先組件不需要知道哪些後代組件使用它提供的屬性
  • 後代組件不需要知道被註入的屬性來自哪裏(可以從多個祖先哪裏獲得)

栗子:

// 父級組件提供 ‘foo‘
var Provider = {
  provide: {
    foo: ‘bar‘
  },
  // ...
}

// 子組件註入 ‘foo‘
var Child = {
  inject: [‘foo‘],
  created () {
    console.log(this.foo) // => "bar"
  }
  // ...
}

//使用一個註入的值作為一個屬性的默認值,Vue 2.2.1 或更高版本
const Child = {
  inject: [‘foo‘],
  props: {
    bar: {
      default () {
        return this.foo
      }
    }
  }
}
//使用一個註入的值作為數據入口,Vue 2.2.1 或更高版本
const Child = {
  inject: [‘foo‘],
  data () {
    return {
      bar: this.foo
    }
  }
}

//在 2.5.0+ 的註入可以通過設置默認值使inject變成可選項,或從一個不同名字的屬性註入
const Child = {
  inject: {
    foo: {
      from: ‘bar‘,
      default: ‘foo‘
    }
  }
}
const Child = {
inject: {
foo: {
from: ‘bar‘,
default: () => [1, 2, 3]
}
}
}

選項的其他key

name

組件的選項,組件名

delimiters

Vue默認的插值是雙大括號{{}},delimiters定義插值符號新的寫法:

new Vue({
  delimiters: [‘${‘, ‘}‘]//插值形式就變成了${}。代替了{{ }}
})

functional

設置為 true 後,就可以讓組件變為無狀態、無實例的函數化組件。因為只是函數,所以渲染的開銷相對來說較小,用一個簡單的 render 函數返回虛擬節點使他們更容易渲染。

函數化的組件中的 Render 函數,提供了第二個參數 context 作為上下文,data、props、slots、children 以及 parent 都可以通過 context 來訪問。

暫時沒搞明白:

Vue學習筆記進階篇——函數化組件

說說 Vue.js 中的 functional 函數化組件:很好的例子

應用場景

函數化組件不常用,它應該應用於以下場景:

  • 需要通過編程實現在多種組件中選擇一種。
  • children、props 或者 data 在傳遞給子組件之前,處理它們。

model

見組件中的:v-model指令用在輸入組件上和用直接用在input上的區別。

v-model 默認把 value 用作 prop 且把 input 用作 event,但是一些輸入類型比如單選框和復選框按鈕可能想使用 value prop 來達到不同的目的,使用 model 選項來重新定義v-model的value和event

inheritAttrs

在使用自定義組件時,給組件設置一些非props的特性,默認會將這些特性幫到根元素上,通過設置inheritAttrs:false。可以禁止根元素繼承這些特性,防止覆蓋根元素已有特性。

$attrs存儲非prop特性(除style和class外),在撰寫基礎組件的時候常會用到。

關於實例的目標掛載元素

如果在實例化時存在el選項,實例將立即進入編譯過程,否則,需要顯式調用 vm.$mount(‘#app‘) 手動開啟編譯。

render 函數若存在,則 Vue 構造函數不會從 template 選項或 el 選項指定的掛載元素中提取出的 HTML 模板編譯渲染函數。

如果 render 函數和 template 屬性都不存在,掛載 DOM 元素的 HTML 會被提取出來用作模板,此時,必須使用 Runtime + Compiler 構建的 Vue 庫。

new Vue({
el: ‘#app‘,
components:{App},
template: ‘<App/>‘
})

實例能代理的屬性

1、data的屬性。

2、props的某個具值屬性。

3、計算屬性,某屬性的get屬性被 實例代理,輸出get的返回值。

computed: {
    add() {
      return 2;
    }
}
vm.add // 2

3、methods的方法

methods: {
    get_num(num) {
      vm.add_test1(num);
    },
    add_test1(num) {
    //...  
    }
}

vue構造函數(根實例化時和組件實例對象選項)參數:選項詳解