Heim > Artikel > Web-Frontend > Beispiel-Tutorial zur Verwendung und Entwicklung von Vue.js-Komponenten
Komponenten
Komponenten können HTML-Elemente erweitern und wiederverwendbaren Code kapseln. Auf hoher Ebene sind Komponenten benutzerdefinierte Elemente, und der Compiler von vue.js fügt ihm in einigen Fällen spezielle Funktionen hinzu auch in Form von nativen HTML-Elementen vorliegen, erweitert um das Attribut is.
Vue.js-Komponenten können als ViewModel-Klassen mit vordefinierten Verhaltensweisen verstanden werden. Eine Komponente kann viele Optionen vordefinieren, die wichtigsten sind jedoch die folgenden:
Vorlage (Vorlage): Die Vorlage deklariert die Zuordnungsbeziehung zwischen den Daten und dem DOM, die letztendlich dem Benutzer angezeigt wird.
Anfangsdaten (Daten): der anfängliche Datenzustand einer Komponente. Bei wiederverwendbaren Komponenten ist dies normalerweise der private Status.
Externe Parameter (Requisiten) akzeptiert: Daten werden über Parameter übertragen und zwischen Komponenten geteilt. Parameter sind standardmäßig unidirektional (von oben nach unten) gebunden, können aber auch explizit bidirektional deklariert werden.
Methoden: Änderungsvorgänge an Daten werden im Allgemeinen innerhalb der Methoden von Komponenten durchgeführt. Benutzereingabeereignisse und Komponentenmethoden können über die v-on-Direktive gebunden werden.
Lebenszyklus-Hooks: Eine Komponente löst mehrere Lifecycle-Hook-Funktionen aus, z. B. erstellt, angehängt, zerstört usw. In diesen Hook-Funktionen können wir eine benutzerdefinierte Logik einkapseln. Im Vergleich zu herkömmlichem MVC ist es verständlich, dass die Logik des Controllers auf diese Hook-Funktionen verteilt ist.
Private Ressourcen (Assets): In Vue.js werden benutzerdefinierte Anweisungen, Filter, Komponenten usw. zusammenfassend als Ressourcen bezeichnet. Da global registrierte Ressourcen leicht zu Namenskonflikten führen können, kann eine Komponente ihre eigenen privaten Ressourcen deklarieren. Private Ressourcen können nur von der Komponente und ihren Unterkomponenten aufgerufen werden.
Darüber hinaus können Komponenten innerhalb desselben Komponentenbaums auch über die integrierte Ereignis-API kommunizieren. Vue.js bietet eine vollständige API zum Definieren, Wiederverwenden und Verschachteln von Komponenten, sodass Entwickler Komponenten verwenden können, um die gesamte Anwendungsschnittstelle wie Bausteine zu erstellen.
Komponenten verbessern die Effizienz, Wartbarkeit und Wiederverwendbarkeit von Code erheblich.
Mit Komponente registrieren
1 Erstellen Sie einen Komponentenkonstruktor:
var MyComponent = Vue.extend({ //选项 })
2 . Verwenden Sie den Konstruktor als Komponente und registrieren Sie ihn bei Vue.component(tag,constructor):
Vue.component('my-component',MyComponent)
3. Im Modul der übergeordneten Instanz , verwenden Sie self. Definieren Sie das Element b98f2d1b8b5d79f8c1b053de334aa7b5 in der Form:
<div id = "example"> <my-component></my-component> </div>
Beispiel:
<div id="example"> <my-component></my-component> </div> // 定义 var MyComponent = Vue.extend({ template: '<div>A custom component!</div>' }) // 注册 Vue.component('my-component', MyComponent) // 创建根实例 new Vue({ el: '#example' })
wird wie folgt gerendert:
<div id = "example"> <div>A custom component!</div> </div>
Die Vorlage der Komponente ersetzt das benutzerdefinierte Element, das nur als dient Befestigungspunkt. Mithilfe der Instanzoption „replace“ können Sie entscheiden, ob eine Ersetzung durchgeführt werden soll.
Lokale Registrierung
Registrierung mit den Instanzoptionskomponenten. Es ist nicht erforderlich, jede Komponente global zu registrieren. Sie können die Komponente nur in anderen Komponenten verwenden:
var Child = Vue.extend({ /* ... */ }) var Parent = Vue.extend({ template: '...', components: { // <my-component> 只能用在父组件模板内 'my-component': Child } })
Diese Kapselung funktioniert auch für andere Ressourcen wie Anweisungen, Filter und Übergänge.
Zucker der Registrierungssyntax
// 在一个步骤中扩展与注册 Vue.component('my-component', { template: '<div>A custom component!</div>' }) // 局部注册也可以这么做 var Parent = Vue.extend({ components: { 'my-component': { template: '<div>A custom component!</div>' } } })
Probleme mit Komponentenoptionen
Die meisten an den Vue-Konstruktor übergebenen Optionen können dies auch tun Wenn Sie in Vue.extend() zusätzlich zu data und el einfach ein Objekt als Datenoption an Vue.extend() übergeben, teilen sich alle Instanzen dasselbe Datenobjekt, daher sollten wir eine Funktion als verwenden Datenoption. Lassen Sie diese Funktion ein neues Objekt zurückgeben:
var MyComponent = Vue.extend({ data: function () { return { a: 1 } } })
Template-Parsing
Vues Vorlage ist eine DOM-Vorlage, die das verwendet Der native Template-Parser des Browsers muss daher ein gültiges HTML-Fragment sein. Einige HTML-Elemente unterliegen Einschränkungen hinsichtlich der Elemente, die darin platziert werden können:
a darf keine anderen interaktiven Elemente enthalten (z. B. Schaltflächen, Links). )
ul und ol können li nur direkt enthalten
select kann nur option und optgroup enthalten
table kann nur thead, tbody, tfoot, tr, caption, col direkt enthalten , colgroup
tr kann nur th und td direkt enthalten
In der Praxis können diese Einschränkungen zu unerwarteten Ergebnissen führen. Obwohl es in einfachen Fällen funktionieren kann, können Sie sich nicht auf das Ergebnis der Erweiterung einer benutzerdefinierten Komponente verlassen, bevor der Browser sie validiert. Beispielsweise ist
750d7c37f87c44b67b1e945084b6bc455a07473c87748fb1bf73f23d45547ab8...4afa15d3069109ac30911f04c56f3338c3b6035d40e49dd3cf5dfe627a1d2a00 keine gültige Vorlage, auch wenn die my-select-Komponente irgendwann erweitert wird 221f08282418e2996498697df914ce4e..18bb6ffaf0152bbe49cd8a3620346341.
Ein weiteres Ergebnis ist, dass benutzerdefinierte Tags (einschließlich benutzerdefinierter Elemente und spezieller Tags wie 8c05085041e56efcb85463966dd1cb7e, d477f9ce7bf77f53fbcf36bec1b69b7a, ec872302d9f7ec49547f9998f4be2186) nicht innerhalb von UL-, Select-, Table- usw. Elementen verwendet werden können liegen innerhalb eingeschränkter Tags. Benutzerdefinierte Tags, die in diesen Elementen platziert werden, werden aus dem Element herausgehoben und falsch gerendert.
Für benutzerdefinierte Elemente sollte das is-Attribut verwendet werden:
f5d188ed2c074f8b944552db028f98a1
<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
Verwenden Sie Requisiten, um Daten zu übergeben.
Der Bereich der Komponenteninstanz ist isoliert. Sie können Requisiten verwenden, um das Array an die untergeordnete Komponente zu übergeben um von der übergeordneten Komponente an die untergeordnete Komponente übergeben zu werden. Sie müssen props explizit mit der props-Option deklarieren:
Vue.component('child', { // 声明 props props: ['msg'], // prop 可以用在模板内 // 可以用 `this.msg` 设置 template: '<span>{{ msg }}</span>' })
und dann eine normale übergeben Zeichenfolge:
<child msg="hello!"></child>
Dynamische Requisiten
用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('child', { template: '#child-template', data: function () { return { msg: 'hello' } }, methods: { notify: function () { if (this.msg.trim()) { this.$dispatch('child-msg', this.msg) this.msg = '' } } } }) // 初始化父组件 // 将收到消息时将事件推入一个数组 var parent = new Vue({ el: '#events-example', data: { messages: [] }, // 在创建实例时 `events` 选项简单地调用 `$on` events: { 'child-msg': 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: '#parent' }) // 访问子组件 var child = parent.$refs.profile
使用Slot分发内容
内容分发:混合父组件的内容与子组件自己的模板的方式,使用特殊的58cb293b8600657fad49ec2c8d37b472元素作为原始内容的插槽。
编译作用域
父组件模板的内容在父组件作用域内编译;子组件模板的内容在子组件作用域内编译。
绑定子组件内的指令到一个组件的根节点:
Vue.component('child-component', { // 有效,因为是在正确的作用域内 template: '<div v-show="someChildProperty">Child</div>', 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: 'body', data: { currentView: 'home' }, components: { home: { /* ... */ }, posts: { /* ... */ }, archive: { /* ... */ } } }) <component :is="currentView"> <!-- 组件在 vm.currentview 变化时改变 --> </component> keep-alive
把切换出去的组件保留在内存中,可以保留它的状态或避免重新渲染。
39a981128a40da37853cce84bffb2ba2
b2b0822175891cddec63f9cdd3f18ba9
2724ec0ed5bf474563ac7616c8d7a3cd
activate钩子
控制组件切换时长,activate 钩子只作用于动态组件切换或静态组件初始化渲染的过程中,不作用于使用实例方法手工插入的过程中。
Vue.component('activate-example', { 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 ermöglicht es der externen Umgebung, Inhalte in die Ansichtsstruktur der Komponente einzufügen.