vue構造函數(根實例化時和組件實例對象選項)參數:選項詳解
實例選項(即傳給構造函數的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 會在一個組件實例創建之前進行驗證,所以實例的屬性 (如 data
、computed
等) 在 default
或 validator
函數中是不可用的。
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、每次進入/離開組件都要做一些事情,用什麽鉤子:
進入的時候可以用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、binding
、vnode
和 oldVnode。
el:指令所綁定的元素,可以用來直接操作 DOM 。
binding:對象,有以下屬性:
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 編譯生成的虛擬節點。移步 VNode API 來了解更多詳情。
oldVnode:上一個虛擬節點,僅在
update
和 componentUpdated
鉤子中可用。
鉤子函數簡寫:
在 bind
和 update
時觸發相同行為,而不關心其它的鉤子,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構造函數(根實例化時和組件實例對象選項)參數:選項詳解