上一篇: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...