上一篇:Vue的表單輸入綁定:https://segmentfault.com/a/11...html
首先咱們要建立一個實例:vue
new Vue({ el:'.exp', // ...... })
要註冊一個全局組件,你可使用 Vue.component(tagName, options)。例如:segmentfault
Vue.component('my-component', { // 選項 })
組件在註冊以後,即可以在父實例的模塊中以自定義元素 < my-component >< /my-component > 的形式使用。要確保在初始化根實例以前註冊了組件:瀏覽器
<div class="exp"> <my-component></my-componetn> </div> <script> Vue.component('my-component',{ template:'<div>這是一個組件</div>' }) new Vue({ el:'.exp', }) </script>
渲染結果:函數
<div class="exp"> <div>這是一個組件</div> </div>
對於自定義標籤名,Vue.js 不強制要求遵循 W3C 規則 (小寫,而且包含一個短槓),儘管遵循這個規則比較好。this
咱們知道,在建立的實例裏面是有data數據的,其實在組件裏也能夠寫數據:spa
Vue.component('my-component'{ templent:'<div><input type="button"></div>', data:function(){ return{ msg:'hello' } } })
注意!組件裏的data必須是一個函數,並將屬性返回code
沒必要在全局註冊每一個組件。經過使用組件實例選項註冊,可使組件僅在另外一個實例/組件的做用域中可用:component
<div class="exp"> <my-component></my-component> </div> <script> var child={ template:'<div>這是一個局部組件</div>' } new Vue({ el:'.exp', components:{ 'my-component':child } }) </script>
渲染結果和上一個例子是同樣的。htm
咱們來看看全局註冊和局部註冊的區別:
<div class="exp"> <my-component></my-component> </div> <div class="exp1"> <first></first> </div> <script> //全局註冊 Vue.component('my-component',{ template:'<div>這是一個全局組件</div>' }); new Vue({ el:'.exp', }); // 局部註冊 var child={ template:'<div>這是一個局部組件</div>' }; new Vue({ el:'.exp1', components:{ 'first':child } }); </script>
局部註冊的組件,只能在 .exp1 內使用,拿給 .exp 是不能夠的,固然咱們把全局註冊的組件給 .exp1 ,是能夠生效的。
當使用 DOM 做爲模板時 (例如,將 el 選項掛載到一個已存在的元素上), 你會受到 HTML 的一些限制,由於 Vue 只有在瀏覽器解析和標準化 HTML 後才能獲取模板內容。尤爲像這些元素 < ul >,< ol >,< table >,< select > 限制了能被它包裹的元素,而一些像 < option > 這樣的元素只能出如今某些其它元素內部。
好比:
<div class="exp"> <table> <my-component></my-component> </table> </div> <script> Vue.component('my-component',{ template:'<tr><td>1</td><td>2</td></tr>' }); new Vue({ el:'.exp', }); </script>
如上,這樣的寫法在DOM裏渲染時會反正錯誤:
<tr>...</tr> <table></table>
爲了解決,就須要使用 is 屬性
<table> <tr is="my-component"></tr> </table>
有時候咱們可能要在組件裏寫不少的標籤,若是通通像上面那樣寫的話,看起來很費勁,這時候就可使用模板字符串:
< script type="text/x-template" >< /script >
<div class="exp"> <table> <tr is="my-component"></tr> </table> </div> <!-- 模板字符串 --> <script type="text/x-templent" id="tmp"> <tr> <td>1</td> <td>3</td> <td>4</td> <td>3</td> </tr> </script> <script> Vue.component('my-component',{ template:'#tmp'//調用模板字符串的 id }); new Vue({ el:'.exp', }); </script>
這樣寫的話就比較直觀了。
組件實例的做用域是孤立的。這意味着不能 (也不該該) 在子組件的模板內直接引用父組件的數據。要讓子組件使用父組件的數據,咱們須要經過子組件的 props 選項。
子組件要顯式地用 props 選項聲明它期待得到的數據:
<div class="exp"> <tk msg="hello"></tk> </div> <script type="text/x-templent" id="tmp"> <div> <input type="button" v-on:click="alertMsg" value="彈框"> </div> </script> <script> var tkTmp={ template:"#tmp", //聲明props props:['msg'], methods:{ alertMsg:function(){ alert(this.msg) } } }; new Vue({ el:'.exp', components:{ 'tk':tkTmp } }); </script>
在上面的例子中,咱們要在子組件 tk 裏傳一個參數,就須要使用 prop 屬性.
這種方式是靜態綁定的方法,還有就是利用 v-bind 指令進行動態綁定:
<tk v-bind:msg="msg"></tk>
HTML 特性是不區分大小寫的。因此,當使用的不是字符串模板,camelCased (駝峯式) 命名的 prop 須要轉換爲相對應的 kebab-case (短橫線隔開式) 命名:
ue.component('child', { // camelCase in JavaScript props: ['myMessage'], template: '<span>{{ myMessage }}</span>' })
<!-- kebab-case in HTML --> <child my-message="hello!"></child>
每一個 Vue 實例都實現了事件接口 (Events interface),即:
$on(enentName) 監聽事件
$emit(eventName) 觸發事件
咱們可使用 $emit 來用子組件觸發父組件的事件:
<div class="exp"> <tk v-bind:msg="msg"></tk> <tk msg="HELLO WORDL" v-on:jieshou="jieshoufn"></tk> </div> <script type="text/x-templent" id="tmp"> <div> <input type="button" v-on:click="alertMsg" value="彈框"> </div> </script> <script> var tkTmp={ template:"#tmp", props:['msg'], methods:{ alertMsg:function(){ alert(this.msg), this.$emit("jieshou","abc","def") } } }; new Vue({ el:'.exp', data:{ msg:'hello' }, components:{ 'tk':tkTmp }, methods:{ jieshoufn:function(){ alert(2); } } }); </script>
當咱們點擊第二個按鈕時,就會觸發父組件內的 alert 事件。
其實咱們也能夠傳遞參數,由父組件接收:
this.$emit("jieshou","abc")
有時候兩個組件也須要通訊 (非父子關係)。在簡單的場景下,可使用一個空的 Vue 實例做爲中央事件總線:
<div class="exp"> <tk></tk> <pop></pop> </div> <script type="text/x-templent" id="tmp"> <div> <input type="button" v-on:click="alertMsg" value="彈框"> </div> </script> <script> var bus=new Vue();//空的 vue 實例 var tkTmp={ template:"#tmp", methods:{ alertMsg:function(){ bus.$emit("pass",1,2)//觸發事件 } } }; var pop={ template:'<div>2333</div>', mounted:function(){ bus.$on("pass",function(arg1,arg2){//監聽事件 console.log(arg1) console.log(arg2) }) } } new Vue({ el:'.exp', components:{ 'tk':tkTmp, 'pop':pop } }); </script>
這部分官方文檔說的有點囉嗦,我這邊就合到一塊說吧。直接上個例子:
<style> .box{ margin: 10px; width: 150px; border: 1px solid #ccc; } .box-header, .box-footer{ height: 30px; background: sandybrown; } .box-body{ min-height: 100px; } </style> <body> <div class="exp"> <box> <h2 slot="title">Slot內容分發<h2> <p>爲了讓組件能夠組合,咱們須要一種方式來混合父組件的內容與子組件本身的模板。這個過程被稱爲 內容分發 (或 「transclusion」 若是你熟悉 Angular)。Vue.js 實現了一個內容分發 API,參照了當前 Web 組件規範草案,使用特殊的 <slot> 元素做爲原始內容的插槽。</p> <p slot="foot">分發完成</p> </box> </div> <script type="text/x-template" id="tmp"> <div class="box"> <div class="box-header"><slot name="title"></slot></div> <div class="box-body"> <slot></slot> </div> <div class="box-footer"><slot name="foot"></slot> </div> </div> </script> <script> var box={ template:"#tmp", } new Vue({ el:'.exp', components:{ "bilibili":box } }) </script> </body>
< slot >被成爲插口,在組件中,咱們須要使用 slot 插口預留一個位置,以方便分發內容。如上,在放置正文內容的地方,咱們直接插入一對 slot 標籤標記出正文內容的位置。對於頁面標題和頁腳等特殊的位置,咱們就須要"具名Slot",用一個特殊的屬性 name 來配置如何分發內容。多個 slot 能夠有不一樣的名字。具名 slot 將匹配內容片斷中有對應 slot 特性的元素。
上一篇:Vue的表單輸入綁定:https://segmentfault.com/a/11...