组件
组件 (Component) 是 Vue.js 最强大的功能之一。组件可以扩展 HTML 元素,封装可重用的代码。在较高层面上,组件是自定义元素.
注册
全局注册
<div id="app">
<my-component></my-component>
</div>
<script>
//注册全局组件
Vue.compnent('my-component',{
template:'<div><input type="button" value="弹出" @click="tanshu"/></div>' ,
data:function(){
return{
msg1:'helloworld'
};
},
methods:{
tanchu:function(){
alert(this.msg1);
}
}
});
//初始化根实例
var vm=new Vue({
el:'#app',
date:{
msg:'hello world!',
},
});
</script>
局部注册
不必在全局注册每个组件。通过使用组件实例选项注册,可以使组件仅在另一个实例/组件的作用域中可用:
//初始化根实例
<div id="app1">
<my-component1></my-component1>
</div>
<script>
//局部注册
var zujian={
template:'<div><input type="button" value="tanchu" @click="tanshu"/></div>' ,
data:function(){
return{
msg1:'helloworld'
};
},
methods:{
tanchu:function(){
alert(this.msg1);
}
}
});
//初始化根实例
var vm=new Vue({
el:'#app1',
date:{
msg:'hello world!',
},
components:{
'my-component1':zujian
}
});
</script>
配置组件
像这些元素 <ul>,<ol>,<table>,<select> 限制了能被它包裹的元素,而一些像 <option> 这样的元素只能出现在某些其它元素内部。在自定义组件中使用这些受限制的元素时会导致一些问题,例如:
<table>
<my-row>...</my-row>
</table>
自定义组件 <my-row> 被认为是无效的内容,因此在渲染的时候会导致错误。变通的方案是使用特殊的 is 属性:
<table>
<tr is="my-row"></tr>
</table>
应当注意,如果您使用来自以下来源之一的字符串模板,这些限制将不适用:
<script type="text/x-template">
JavaScript 内联模板字符串
.vue 组件
data必须是函数
<div id="app">
<table>
<tr is="component-tr"></tr>
<tr is="component-tr"></tr>
<tr is="component-tr"></tr>
<tr is="component-tr"></tr>
</table>
</div>
<script type="text/x-template" id="tpl1">
<tr>
<td>{{msg}}</td><td>2</td><td>3</td><td>4</td>
</tr>
</script>
<script>
Vue.compnentIr={
template:'#tpl1',
data:function{
return{
msg:'helloworld'
}
}
};
var vm=new Vue({
el:'#app1',
});
</script>
组件通讯
组件 A 在它的模板中使用了组件 B。它们之间必然需要相互通信:父组件要给子组件传递数据,子组件需要将它内部发生的事情告知给父组件。
父子通讯
在 Vue 中,父子组件的关系可以总结为 props down, events up。父组件通过 props 向下传递数据给子组件,子组件通过 events 给父组件发送消息。
prop
要让子组件使用父组件的数据,我们需要通过子组件的 props 选项。
Vue.component('child', {
// 声明 props
props: ['message'],
// 就像 data 一样,prop 可以用在模板内
// 同样也可以在 vm 实例中像“this.message”这样使用
template: '<span>{{ message }}</span>'
})
<child message="hello!"></child>
camelCased vs kebab-case
HTML 特性是不区分大小写的。所以,当使用的不是字符串模板,camelCased (驼峰式) 命名的 prop 需要转换为相对应的 kebab-case (短横线隔开式) 命名:
Vue.component('child', {
// camelCase in JavaScript
props: ['myMessage'],
template: '<span>{{ myMessage }}</span>'
})
<!-- kebab-case in HTML -->
<child my-message="hello!"></child>
动态prop
要动态地绑定父组件的数据到子模板的 props,与绑定到任何普通的HTML特性相类似,就是用 v-bind。
<div>
<input v-model="parentMsg">
<br>
<child v-bind:my-message="parentMsg"></child>
</div>
子父传递数据 (emit)
每个 Vue 实例都实现了事件接口 (Events interface),即:
使用 $on(eventName) 监听事件
使用 $emit(eventName) 触发事件
<div id="app">
<tk v-bind:my-message="msg"></tk>
<tk msg="helloworld2" v-on:jieshou="jieshoufn"></tk>
</div>
<script type="text/x-template" id="tkTpl">
<div>
<input type="button" @click="alertMsg" value="弹框"/>
</div>
</script>
<script>
var tkTpl={
template:'#tkTpl',
props:['myMessage'],
methods:{
alertMsg:function(){
alert(this.myMessage);
this.$emit("jieshou","abc","def");
}
}
};
var vm=new Vue({
el:'#app',
compnents:{
tk:tkTpl
},
data:{
msg:"hello vue"
},
methods:{
jieshoufn:function(){
alert(2);
}
}
});
</script>
非父子组件通信
有时候两个组件也需要通信 (非父子关系)。在简单的场景下,可以使用一个空的 Vue 实例作为中央事件总线:
var bus = new Vue()
// 触发组件 A 中的事件
bus.$emit('id-selected', 1)
// 在组件 B 创建的钩子中监听事件
bus.$on('id-selected', function (id) {
// ...
})
<div id="app">
<tk v-bind:my-message="msg"></tk>
<panel-tpl></panel-tpl>
</div>
<script type="text/x-template" id="tkTpl">
<div>
<input type="button" @click="alertMsg" value="弹框"/>
</div>
</script>
<script>
var bus=new Vue();
var tkTpl={
template:'#tkTpl',
props:['myMessage'],
methods:{
alertMsg:function(){
bus.$enit("passid",1,2);
}
}
};
var panelTpl={
template='<div>{{id}}</div>',
data:function(){
return{
id:0
};
},
mounted:function(){
var that=this;
bus.$on("passid",function(arg1,arg2){
this.id=arg1+arg2;
});
}
}
var vm=new Vue({
el:'#app',
compnents:{
"tk":tkTpl,
},
data:{
msg:"hello vue"
},
});
</script>
## 使用slot分发内容
注意两点:
1.<app> 组件不知道它会收到什么内容。 这是由使用 <app> 的父组件决定的。
2.<app> 组件很可能有它自己的模板。
<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>
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。