給 props 屬性設置多個類型這個技巧在開發組件的時候用的較多,爲了更大的容錯性考慮,同時代碼也更加人性化:
[JavaScript] 純文本查看 複製代碼
?vue
export default {
props: {node
width: { type: [String, Number], default: '100px' } // 或者這樣 // width: [String, Number]
}
}面試
好比一個 <my-button> 上暴露了一個 width 屬性,咱們既能夠傳 100px,也能夠傳 100 :
[HTML] 純文本查看 複製代碼
?ajax
<!-- my-button.vue -->
<template>
<button :style="computedWidth">{{ computedWidth }}</button>
</template>數組
<script>
export default {瀏覽器
props: { width: [String, Number] }, computed: { computedWidth () { let o = {} if (typeof this.width === 'string') o.width = this.width if (typeof this.width === 'number') o.width = this.width + 'px' return o } }
}
</script>
使用:
[HTML] 純文本查看 複製代碼
?緩存
<!-- 在其餘組件中使用 -->
<template>
<my-button width="100px"></my-button>
<!-- or -->
<my-button :width="100"></my-button>
</template>
阻止 <el-form> 默認提交行爲有時候咱們在用餓了麼組件 <el-form> 在文本框中鍵入 enter 快捷鍵的時候會默認觸發頁面刷新。咱們能夠加入以下代碼解決其默認行爲:
[HTML] 純文本查看 複製代碼
?app
<el-form @submit.native.prevent>
...
</el-form>
data 初始化由於 props 要比 data 先完成初始化,因此咱們能夠利用這一點給 data 初始化一些數據進去,看代碼:
[JavaScript] 純文本查看 複製代碼
?函數
export default {
data () {工具
return { buttonSize: this.size }
},
props: {
size: String
}
}
除了以上,子組件的 data 函數也能夠有參數,且該參數是當前實例對象。全部咱們能夠利用這一點作一些本身的判斷。如,改寫上面的代碼:
[JavaScript] 純文本查看 複製代碼
?
export default {
data (vm) {
return { buttonSize: vm.size }
},
props: {
size: String
}
}
template咱們在作 v-if 判斷的時候,能夠把判斷條件放在 template 組件上,最終的渲染結果將不包含 <template> 元素。
[HTML] 純文本查看 複製代碼
?
<template>
<div class="box">
<template v-if="isVal"> <h2>...</h2> </template> <template v-else> <h2>...</h2> </template>
</div>
</template>
v-for 也一樣適用。
Lifecycle hook生命週期鉤子能夠是一個數組類型,且數組中的函數會依次執行。
[JavaScript] 純文本查看 複製代碼
?
export default {
...
created: [
function one () {
console.log(1)
},
function two () {
console.log(2)
}
]
...
}
沒什麼用,知道就好了。事實上生命週期鉤子還能夠做用於 DOM 元素上,利用這一點,咱們能夠用父組件中的方法來初始化子組件的生命週期鉤子:
[HTML] 純文本查看 複製代碼
?
<!-- Child.vue -->
<template>
<h3>I'm child!</h3>
</template>
<!-- Parent.vue -->
<template>
<child @hook:created="handleChildCreated"></child>
</template>
<script>
import Child from './child.vue'
export default {
components: [ Child ], methods: { handleChildCreated () { console.log('handle child created...') } }
}
</script>
其餘鉤子雷同,再也不贅述。
v-for在用 v-for 遍歷數組的時候,咱們通常都會錯誤的這樣去作,舉個栗子:
v-for 和 v-if 放在同一個元素上使用:
[HTML] 純文本查看 複製代碼
?
<template>
<ul class="items">
<!-- 只有激活的用戶才能夠顯示 --> <li v-for="(user, index) in users" v-if="user.isActive" :key="user.id"> {{ user.name }} </li>
</ul>
</template>
因爲 v-for 和 v-if 放在同一個元素上使用會帶來一些性能上的影響,官方給出的建議是在計算屬性上過濾以後再進行遍歷。因此平時開發不推薦一塊兒使用,知道有這回事便可,不至於面試時不知道。 關於爲何不推薦放在一塊兒使用,參見 避免-v-if-和-v-for-用在一塊兒。
混合若是好多組件都共用到一些像 props、data、methods 等,能夠單獨抽出來放到 mixins 混合器中。好比,在用戶管理列表中使用。
分頁混合器:
[JavaScript] 純文本查看 複製代碼
?
// paging-mixin.vue
export default {
props: {
pageSize: 1, pageLength: 10, currentPage: 1 total: 20
},
methods: {
/** * 上一頁 */ prevPage (page) { ... }, /** * 下一頁 */ nextPage (page) { ... } /** * 跳轉到當前頁 */ currentPage (page) { ... }
}
}
Users.vue:
[HTML] 純文本查看 複製代碼
?
<template>
<div class="user-model">
<my-table :data="users"></my-table> <my-paging :page-length="pageLength" :page-size="pageSize" :current-page="currentPage" :total="total"> </my-paging>
</div>
</template>
<script>
import PagingMixin from '../mixins/paging-mixin.vue'
export default {
mixins: [PagingMixin], data () { return { users: [], pageLength: 10, pageSize: 1, currentPage: 1, total: 20 } }
}
</script>
不用每一個頁面都寫一遍 props 和 methods 了。
render 函數下面是一段簡單的 template 模板代碼:
[HTML] 純文本查看 複製代碼
?
<template>
<div class="box">
<h2>title</h2> this is content
</div>
</template>
咱們用渲染函數來重寫上面的代碼:
[JavaScript] 純文本查看 複製代碼
?
export default {
render (h) {
let _c = h return _c('div', { class: 'box'}, [_c('h2', {}, 'title'), 'this is content'])
}
}
事實上,Vue 會把模板(template)編譯成渲染函數(render)。上面的 template 模板會被編譯成以下渲染函數:
[JavaScript] 純文本查看 複製代碼
?
let render = function () {
return _c('div',
{staticClass:"box"}, [_c('h2', [_v("title")]), _v("this is content")])
}
是否是很像? 正如官方說的,渲染函數比 template 更接近編譯器。若是用一個流程圖來解釋的話,大概是這個樣子:
template ↓預編譯工具(vue-loader + vue-template-compile) ↓ render ↓resolve vnode複製代碼具體參見 Vue聲明週期圖示。
渲染函數用處:
開發組件庫,Element 源碼用的都是 render
封裝一些高階組件。組件裏面嵌套組件就是高階組件,前提是要知足組件三要素:props、event、slot
用於處理一些複雜的邏輯判斷。若是咱們一個組件裏面有不少 v-if 判斷的話,用模板就顯得不合適了,這個時候能夠用渲染函數來輕鬆處理
errorCaptured捕獲一個來自子孫組件的錯誤時被調用。有時候當咱們想收集錯誤日誌,卻不想把錯誤暴露到瀏覽器控制檯的時候,這頗有用。下面是個例子:
Child.vue
[HTML] 純文本查看 複製代碼
?
<template>
<!-- 省略一些無關代碼 -->
</template>
<script>
export default {
mounted () { // 故意把 console 寫錯 consol.log('這裏會報錯!') }
}
</script>
Parent.vue
[HTML] 純文本查看 複製代碼
?
<template>
<child></child>
</template>
<script>
import Child from './Child.vue'
export default {
components: [ Child ], /** * 收到三個參數: * 錯誤對象、發生錯誤的組件實例 * 以及一個包含錯誤來源信息的字符串。 * 此鉤子能夠返回 false 以阻止該錯誤繼續向上傳播。 */ errorCaptured (err, vm, info) { console.log(err) // -> ReferenceError: consle is not defined ... console.log(vm) // -> {_uid: 1, _isVue: true, $options: {…}, _renderProxy: o, _self: o,…} console.log(info) // -> `mounted hook` // 告訴咱們這個錯誤是在 vm 組件中的 mounted 鉤子中發生的 // 阻止該錯誤繼續向上傳播 return false }
}
</script>
關於 errorCaptured 更多說明,請移步官網-> 。
v-once經過 v-once 建立低開銷的靜態組件。渲染普通的 HTML 元素在 Vue 中是很是快速的,但有的時候你可能有一個組件,這個組件包含了大量靜態內容。在這種狀況下,你能夠在根元素上添加 v-once 特性以確保這些內容只計算一次而後緩存起來,就像這樣:
[HTML] 純文本查看 複製代碼
?
<template>
<div class="box" v-once>
<h2> 用戶協議 </h2> ... a lot of static content ...
</div>
</template>
只渲染元素和組件一次。隨後的從新渲染,元素/組件及其全部的子節點將被視爲靜態內容並跳過。這能夠用於優化更新性能。關於 v-once 更多介紹,請移步官網->。
slot-scope做用域插槽。vue@2.5.0 版本之前叫 scope,以後的版本用 slot-scope 將其代替。除了 scope 只能夠用於 <template> 元素,其它和 slot-scope 都相同。
用過 Element 組件的同窗都知道,當咱們在使用<el-table> 的時候會看到以下代碼:
Element@1.4.x 的版本:
[HTML] 純文本查看 複製代碼
?
<el-table-column label="操做">
<template scope="scope">
<el-button
size="small" @click="handleEdit(scope.$index, scope.row)">編輯</el-button>
<el-button
size="small" type="danger" @click="handleDelete(scope.$index, scope.row)">刪除</el-button>
</template>
</el-table-column>
但在 2.0 以後的版本替換成了 slot-scope。
Element@2.0.11:
[HTML] 純文本查看 複製代碼
?
<el-table-column label="操做">
<template slot-scope="scope">
<el-button size="mini" @click="handleEdit(scope.$index, scope.row)">編輯</el-button> <el-button size="mini" type="danger" @click="handleDelete(scope.$index, scope.row)">刪除</el-button>
</template>
</el-table-column>
複製代碼說白了,slot-scope 至關於函數的回調,我把結果給你,你想怎麼處理就怎麼處理,一切隨你:
[JavaScript] 純文本查看 複製代碼
?
function getUserById (url, data, callback) {
$.ajax({
url, data, success: function (result) { callback(result) }
})
}
// 使用
getUserById('/users', { id: 1 }, function (response) {
// 拿到數據並開始處理本身的頁面邏輯
})
下面咱們來簡單模擬下 <el-table> 組件內部是怎麼使用 slot-scope 的,看代碼:
模擬的 <el-table> 組件:
[JavaScript] 純文本查看 複製代碼
?
// 定義模板
let template = `
<ul class="table">
<li v-for="(item, index) in data" :key="index">
<!-- 我但願數據由調用者本身處理 --> <!-- 'row' 至關於變量名,隨便定義,好比 aaa,bbb 啥的 --> <slot :row="item"> <!-- 當使用者什麼都沒寫的時候,默認值纔會顯示--> {{ item.name }} </slot>
</li>
</ul>
`
Vue.component('el-table', {
template,
props: {
data: Array, default: []
}
})
在你須要的地方使用 <el-table> 組件:
HTML:
[HTML] 純文本查看 複製代碼
?
<div id="app">
<el-table :data="userData">
<!-- 使用的時候能夠用 template --> <!-- `scope` 也是個變量名,隨便命名不是固定的,好比 foo, bar --> <template slot-scope="scope"> <!-- 其中 `scope.row` 中的 row 就是咱們上邊定義的變量啦--> <!-- `scope.row`返回的是 `item` 對象 --> <template v-if="scope.row.isActived"> <span class="red">{{ scope.row.name }}</span> </template> <template v-else> {{ scope.row.name }} </template> </template>
</el-table>
</div>
JavaScript:
[JavaScript] 純文本查看 複製代碼
?
new Vue({
el: '#app',
data: {
userData: [ {id: 1, name: '張三', isActived: false}, {id: 2, name: '李四', isActived: false}, {id: 1, name: '王五', isActived: true}, {id: 1, name: '趙六', isActived: false}, ]
}
})
CSS:
[CSS] 純文本查看 複製代碼
?
1
2
3
.red {
color: red
}
JavaScript:
[JavaScript] 純文本查看 複製代碼
?
// <el-table>
組件
Vue.component('el-table', {
name: 'ElTable',
render: function (h) {
return h('div', { class: 'el-table' }, this.$slots.default)
},
props: {
data: Array
}
})
// <el-table-column>
Vue.component('el-table-column', {
name: 'ElTableColumn',
render: function (h) {
// 定義一個存放 li 元素的數組 let lis = [], // 獲取父組件中的 data 數組 data = this.$parent.data // 遍歷數組,也就是上面的 `v-for`,生成 `<li>` 標籤 // `this.$scopedSlots.default` 獲取的就是上面 slot-scope 做用於插槽的部分, // 並把 `{ row: item }` 傳給上面的 `scope` 變量 data.forEach((item, index) => { let liEl = h('li', { key: item.id }, [ this.$scopedSlots.default({ row: item }) ]) // 把生成的 li 標籤存到數組 lis.push(liEl) }) return h('ul', { class: 'el-table-column' }, lis)
}
})
在你的頁面這樣來使用:
HTMl:
[HTML] 純文本查看 複製代碼
?
<div id="app">
<el-table :data="list">
<el-table-column> <template slot-scope="scope"> <span class="red" v-if="scope.row.actived">{{ scope.row.name }}</span> <span v-else>{{ scope.row.name }}</span> </template> </el-table-column>
</el-table>
</div>
JavaScript:
[JavaScript] 純文本查看 複製代碼
?
new Vue({
el: '#app',
data: {
list: [ { id: 1, name: '張三', actived: false }, { id: 1, name: '李四', actived: false }, { id: 1, name: '王五', actived: true }, { id: 1, name: '趙六', actived: false }, ]
}})