首頁  >  文章  >  web前端  >  Vue.js元件使用開發實例教程

Vue.js元件使用開發實例教程

高洛峰
高洛峰原創
2016-12-08 11:57:381339瀏覽

元件

元件可以擴充HTML元素,封裝可重複使用的程式碼,在較高的層面上,元件是自訂元素,vue.js的編譯器為它增加特殊功能,在有些情況下,元件也可以是原生HTML元素的形式,以is特性擴充。

Vue.js的元件可以理解為預先定義好了行為的ViewModel類別。一個元件可以預先定義很多選項,但最核心的是以下幾個:

模板(template):模板聲明了資料和最終展現給使用者的DOM之間的映射關係。

初始資料(data):一個組件的初始資料狀態。對於可重複使用的元件來說,這通常是私有的狀態。

接受的外部參數(props):組件之間透過參數來進行資料的傳遞和共享。參數預設是單向綁定(從上到下),但也可以明確地宣告為雙向綁定。

方法(methods):對資料的改動操作一般都在組件的方法內進行。可以透過v-on指令將使用者輸入事件和元件方法進行綁定。

生命週期鉤子函數(lifecycle hooks):一個元件會觸發多個生命週期鉤子函數,例如created,attached,destroyed等等。在這些鉤子函數中,我們可以封裝一些自訂的邏輯。和傳統的MVC相比,可以理解為 Controller的邏輯被分散到了這些鉤子函數中。

私有資源(assets):Vue.js當中將使用者自訂的指令、篩選器、元件等統稱為資源。由於全域註冊資源容易導致命名衝突,一個元件可以宣告自己的私有資源。私有資源只有該元件和它的子元件可以呼叫。

除此之外,同一顆組件樹之內的組件之間還可以透過內建的事件API來進行通訊。 Vue.js提供了完善的定義、重複使用和巢狀元件的API,讓開發者可以像搭積木一樣用元件拼出整個應用的介面。

組件大大提高了程式碼的效率和維護性以及復用率。

使用組件

註冊

1.創建一個組件構造器:

var MyComponent = Vue.extend({
//选项
})

   

2.將構造器用

3.在父實例的模組中以自訂元素的形式使用:

Vue.component('my-component',MyComponent)

   

範例:

<div id = "example">
<my-component></my-component>
</div>

   

範例:

<div id="example">
<my-component></my-component>
</div>
// 定义
var MyComponent = Vue.extend({
template: &#39;<div>A custom component!</div>&#39;
})
// 注册
Vue.component(&#39;my-component&#39;, MyComponent)
// 创建根实例
new Vue({
el: &#39;#example&#39;
})

   

組件的模板取代了自訂元素,自訂元素的作用只是作為一個掛載點。可以用實例選項 replace 決定是否要替換。

局部註冊

用實例選項components註冊,不需要全域註冊每個元件,可以讓元件只能用在其他元件內:

<div id = "example">
<div>A custom component!</div>
</div>

   

這種封裝也適用於其它資源,如指令、其它資源,如指令、它過濾器和過渡。

註冊語法糖

var Child = Vue.extend({ /* ... */ })
var Parent = Vue.extend({
template: &#39;...&#39;,
components: {
// <my-component> 只能用在父组件模板内
&#39;my-component&#39;: Child
}
})

   

組件選項問題

傳入Vue建構器的多數選項也可以用在Vue.extend()中,除了data和el,如果簡單的物件作為選項傳給Vue.extend(),則所有的實例將共享同一個data對象,因此我們應使用一個函數作為data選項,讓這個函數返回一個新對象:

// 在一个步骤中扩展与注册
Vue.component(&#39;my-component&#39;, {
template: &#39;<div>A custom component!</div>&#39;
})
// 局部注册也可以这么做
var Parent = Vue.extend({
components: {
&#39;my-component&#39;: {
template: &#39;<div>A custom component!</div>&#39;
}
}
})

   

Vue的模板模板是DOM模板,使用瀏覽器原生的解析器,所以它必須是有效的HTML片段,一些HTML元素對什麼元素可以放在它裡面有限制,常見的限制有:

a 不能包含其它的交互元素(如按鈕,連結)

ul 和ol 只能直接包含li

select 只能包含option 和optgroup

table 只能直接包含thead, tbody, tfoot, tr, caption, col, colgroups 只能直接包含thead, tbody, tfoot, tr, caption, col, colgroup直接包含th 和td

在實際中,這些限制會導致意外的結果。儘管在簡單的情況下它可能可以工作,但是你不能依賴自訂元件在瀏覽器驗證之前的展開結果。例如

不是有效的模板,即使 my-select 元件最終展開為

另一個結果是,自訂標籤(包括自訂元素和特殊標籤,如

對於自訂元素,應使用is 特性:

var MyComponent = Vue.extend({
data: function () {
return { a: 1 }
}
})

   

Props

使用propsp元傳遞資料

Props

使用 props組件,props是組件資料的一個字段,期望從父組件傳下來,子組件需要顯式地用props選項聲明props:

<tr is="my-component"></tr>
</table>
//<template> 不能用在 <table> 内,这时应使用 <tbody>,<table> 可以有多个 <tbody>
<table>
<tbody v-for="item in items">
<tr>Even row</tr>
<tr>Odd row</tr>
</tbody>
</table>

   

然後向它傳入一個普通字符串

動態props

用v-bind绑定动态props到父组件的数据,每当父组件的数据变化时,也会传导给子组件:

<div>
<input v-model="parentMsg">
<child v-bind:my-message="parentMsg"></child>
//<child :my-message="parentMsg"></child>
</div>

   

props绑定类型

prop默认是单向绑定,当父组件的属性变化时,将传导给子组件,但是反过来不会,这是为了防止子组件无意修改了父组件的状态,可以使用.sync或.once绑定修饰符显式地强制双向或单次绑定:

<!-- 默认为单向绑定 -->
<child :msg="parentMsg"></child>
<!-- 双向绑定 -->
<child :msg.sync="parentMsg"></child>
<!-- 单次绑定 -->
<child :msg.once="parentMsg"></child>

   

如果 prop 是一个对象或数组,是按引用传递。在子组件内修改它会影响父组件的状态,不管是使用哪种绑定类型。

父子组件通信

父链

子组件可以用this.$parent访问它的父组件,根实例的后代可以用this.$root访问它,父组件有一个数组this.$children,包含它所有的子元素

自定义事件

Vue实例实现了一个自定义事件接口,用于在组件树中通信,这个事件系统独立于原生DOM事件,用法也不同,每一个Vue实例都是一个事件触发器:

使用 $on() 监听事件;

使用 $emit() 在它上面触发事件;

使用 $dispatch() 派发事件,事件沿着父链冒泡;

使用 $broadcast() 广播事件,事件向下传导给所有的后代。

不同于 DOM 事件,Vue 事件在冒泡过程中第一次触发回调之后自动停止冒泡,除非回调明确返回 true。

<!-- 子组件模板 -->
<template id="child-template">
<input v-model="msg">
<button v-on:click="notify">Dispatch Event</button>
</template>
<!-- 父组件模板 -->
<div id="events-example">
<p>Messages: {{ messages | json }}</p>
<child></child>
</div>
// 注册子组件
// 将当前消息派发出去
Vue.component(&#39;child&#39;, {
template: &#39;#child-template&#39;,
data: function () {
return { msg: &#39;hello&#39; }
},
methods: {
notify: function () {
if (this.msg.trim()) {
this.$dispatch(&#39;child-msg&#39;, this.msg)
this.msg = &#39;&#39;
}
}
}
})
// 初始化父组件
// 将收到消息时将事件推入一个数组
var parent = new Vue({
el: &#39;#events-example&#39;,
data: {
messages: []
},
// 在创建实例时 `events` 选项简单地调用 `$on`
events: {
&#39;child-msg&#39;: function (msg) {
// 事件回调内的 `this` 自动绑定到注册它的实例上
this.messages.push(msg)
}
}
})

   

效果:

使用v-on绑定自定义事件

在模板中子组件用到的地方声明事件处理器,为此子组件可以用v-on监听自定义事件:

4084e2349312ebcd04e4de37381def6c7d4dd9c7239aac360e401efe89cbb393

当子组件触发了 "child-msg" 事件,父组件的 handleIt 方法将被调用。所有影响父组件状态的代码放到父组件的 handleIt 方法中;子组件只关注触发事件。

子组件索引

使用v-ref为子组件指定一个索引ID,可以直接访问子组件

<div id="parent">
<user-profile v-ref:profile></user-profile>
</div>
var parent = new Vue({ el: &#39;#parent&#39; })
// 访问子组件
var child = parent.$refs.profile

   

使用Slot分发内容

内容分发:混合父组件的内容与子组件自己的模板的方式,使用特殊的58cb293b8600657fad49ec2c8d37b472元素作为原始内容的插槽。

编译作用域

父组件模板的内容在父组件作用域内编译;子组件模板的内容在子组件作用域内编译。

绑定子组件内的指令到一个组件的根节点:

Vue.component(&#39;child-component&#39;, {
// 有效,因为是在正确的作用域内
template: &#39;<div v-show="someChildProperty">Child</div>&#39;,
data: function () {
return {
someChildProperty: true
}
}
})

   

类似地,分发内容是在父组件作用域内编译。

单个slot

父组件的内容将被抛弃,除非子组件模板包含58cb293b8600657fad49ec2c8d37b472,如果子组件模板只有一个没有特性的slot,父组件的整个内容将插到slot所在的地方并替换它。

58cb293b8600657fad49ec2c8d37b472 标签的内容视为回退内容。回退内容在子组件的作用域内编译,当宿主元素为空并且没有内容供插入时显示这个回退内容。

假定 my-component 组件有下面模板:

<div>
<h1>This is my component!</h1>
<slot>

   

如果没有分发内容则显示我。

</slot>
</div>

   

父组件模板:

<my-component>
<p>This is some original content</p>
<p>This is some more original content</p>
</my-component>

   

渲染结果:

<div>
<h1>This is my component!</h1>
<p>This is some original content</p>
<p>This is some more original content</p>
</div>

   

具名slot

58cb293b8600657fad49ec2c8d37b472元素可以用一个特殊特性name配置如何分发内容,多个slot可以有不同的名字,具名slot将匹配内容片段中有对应slot特性的元素。

仍然可以有一个匿名 slot,它是默认 slot,作为找不到匹配的内容片段的回退插槽。如果没有默认的 slot,这些找不到匹配的内容片段将被抛弃。

动态组件

多个组件可以使用同一个挂载点,然后动态地在它们之间切换,使用保留的8c05085041e56efcb85463966dd1cb7e元素,动态地绑定到它的is特性:

new Vue({
el: &#39;body&#39;,
data: {
currentView: &#39;home&#39;
},
components: {
home: { /* ... */ },
posts: { /* ... */ },
archive: { /* ... */ }
}
})
<component :is="currentView">
<!-- 组件在 vm.currentview 变化时改变 -->
</component>
   
keep-alive

把切换出去的组件保留在内存中,可以保留它的状态或避免重新渲染。

39a981128a40da37853cce84bffb2ba2
b2b0822175891cddec63f9cdd3f18ba9
2724ec0ed5bf474563ac7616c8d7a3cd

activate钩子

控制组件切换时长,activate 钩子只作用于动态组件切换或静态组件初始化渲染的过程中,不作用于使用实例方法手工插入的过程中。

Vue.component(&#39;activate-example&#39;, {
activate: function (done) {
var self = this
loadDataAsync(function (data) {
self.someData = data
done()
})
}
})

   

transition-mode

transition-mode 特性用于指定两个动态组件之间如何过渡。

在默认情况下,进入与离开平滑地过渡。这个特性可以指定另外两种模式:

in-out:新组件先过渡进入,等它的过渡完成之后当前组件过渡出去。

out-in:当前组件先过渡出去,等它的过渡完成之后新组件过渡进入。

示例:

<!-- 先淡出再淡入 -->
<component
:is="view"
transition="fade"
transition-mode="out-in">
</component>
.fade-transition {
transition: opacity .3s ease;
}
.fade-enter, .fade-leave {
opacity: 0;
}

   

Vue.js 组件 API 来自三部分——prop,事件和 slot:

prop 允许外部环境传递数据给组件;

事件 允许组件触发外部环境的 action;

slot 允許外部環境插入內容到組件的視圖結構內。


陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn