Vue.js - 组件
一、全局组件注册
用data属性
- data必须是一个函数
- 组件的模板内容必须是一个单个的根元素
- 组件模板内容可以是模板字符串
- 注意事项:在字符串模板中,用驼峰的方式使用组件,但是在普通的标签模板中,必须使用短横线的方式使用组件
eg:添加点击增加2
<script type="text/javascript">
window.onload = function () {
Vue.component('buttonCounter',{可以用驼峰命名法
data: function () {
return{
count: 0,
}
},
template:`
<button @click="count++">
点击了{{count}}次
</button>`,
})
const vm = new Vue({
el:'#app',
})
}
</script>
</head>
<body>
<div id="app">
<button-counter></button-counter> 在标签模板中不能使用驼峰命名法
<button-counter></button-counter>
</div>
</body>
二、局部组件注册
component属性
<script type="text/javascript">
window.onload = function () {
var HelloWorld = {
data:function () {
return {
msg:'HelloWorld'
}
},
template: '<div>{{msg}}</div>'
};
var HelloTom = {
data:function () {
return {
msg:'HelloTom'
}
},
template: '<div>{{msg}}</div>'
};
const vm = new Vue({
el:'#app',
data:{
},
components:{
'hello-world':HelloWorld,
'hello-tom':HelloTom,
}
});
}
</script>
</head>
<body>
<div id="app">
<hello-world></hello-world>
<hello-tom></hello-tom>
</div>
</body>
三、组件间的数据交互
3.1父组件向子组件传值
- 组件内部通过props接受传递过来的值
- 父组件中通过属性将值传递给子组件
<script type="text/javascript">
window.onload = function () {
Vue.component('menu-item',{
props:['title'] 子组件通过props接受
data:function () {
return {
msg:'子组件本身的数据'
}
},
template:'<div>{{msg + "------" + title}}</div>'
});
const vm = new Vue({
el:'#app',
data:{
pmsg:'父组件中的内容'
},
})
}
</script>
</head>
<body>
<div id="app">
<div>{{pmsg}}</div> 父组件通过title属性值来传值
<menu-item title = '来自父组件的值'></menu-item>
</div>
</body>
- 通过v-bind具体的绑定一个属性值
<script type="text/javascript">
window.onload = function () {
Vue.component('menu-item',{
props:['title','content'],//子组件通过props接受
data:function () {
return {
msg:'子组件本身的数据'
}
},
template:'<div>{{msg + "------" + title + content}}</div>'
});
const vm = new Vue({
el:'#app',
data:{
pmsg:'父组件中的内容',
ptitle:'动态绑定属性'
},
})
}
</script>
</head>
<body>
<div id="app">
<div>{{pmsg}}</div>
<menu-item :title = 'ptitle' content = 'hello'></menu-item>
</div>
</body>
3.2props的属性名规则
- 在props中使用驼峰形式,html模板中使用短横线方式
- 字符串形式的模板中没有这个限制
- 显示原始数值的算术,则用v-bind的方式
<script type="text/javascript">
window.onload = function () {
Vue.component('menu-item',{
props:['title'],//子组件通过props接受
data:function () {
return {
msg:'子组件本身的数据'
}
},
template:'<div>{{title + 12}}</div>'
});
const vm = new Vue({
el:'#app',
data:{
ptitle:'动态绑定属性'
},
})
}
</script>
</head>
<body>
<div id="app">
<menu-item title = '12'></menu-item> 不用v-bind的形式,显示的是字符串
<menu-item :title = '12'></menu-item> 用v-bind的方式现实的是数值
</div>
</body>
显示结果:
- props传递数据的原则:单向数据流
只允许父组件传递数值到子组件
3.3:子组件向父组件传值
-
子组件通过自定义事件向父组件传递信息
-
父组件监听子组件的事件
类比于现实中的实例:比如儿子给父亲打钱。儿子对应子组件,父亲对应父组件,请按顺序看。
<script type="text/javascript">
window.onload = function () {
Vue.component("child",{
data(){
return {
childname:"子组件状态"
}
},
template:`
<div>
child组件
<button @click="payMoney">click</button> 3:儿子收到卡号后的行为是执行打钱行动,payMoney()函数,转4:
</div>
`,
methods:{
payMoney(){ 4:转钱的卡号是myevent,数额是1000.(此处的1000就是个参数),this.$emit是查询卡号的必要步骤 转5:
this.$emit("myevent",1000)
}
}
});
const vm = new Vue({
el:'#app',
data:{
},
methods:{
handleEvent(ev) { 2:银行卡的作用:收到传来的钱后再控制台中显示收到钱了console.log();转3:
console.log("父组件收到钱了",ev);
}
}
})
}
</script>
</head>
<body>
<div id="app">//父组件,child为子组件
父组件
<child @myevent = "handleEvent($event)"></child> 1:父亲先给儿子(child组件)提供一张银行卡,这张银行卡的号叫myevent,事件用@来监听,这张银行卡的作用是handleEvent()函数。转2:
</div> 5:父亲的银行卡需要接受1000(接受子组件中的参数),固定方式是$event
</body>
结果显示:
四、组件refs通信
- ref 放在标签上,拿到的是原生节点
- ref 放在组件上,拿到的是组件对象
<script type="text/javascript">
window.onload = function () {
Vue.component("child",{
template:`
<div>
child
</div>
`,
data(){
return {
childName:"子组件的状态"
}
}
})
const vm = new Vue({
el:'#app',
data:{
},
methods:{
handle(){
console.log(this.$refs); this.$refs会获取父组件中ref指向,即两个dom节点,一个子节点没有mychild,一个父节点mytext
// console.log(this.$refs.mychild); 获取的是子节点
}
}
})
}
</script>
</head>
<body>
<div id="app">
<input type="text" ref = "mytext">
<child ref = "mychild"></child>
<button @click="handle">点击</button>
</div>
</body>
五、组件非父子通信(兄弟通信)
事件总线mounted
- mounted,生命周期进行监听,在当前组件dom创建完就会调用
- 创建一个空的父组件vue实例bus
- 用bus. o n 来 监 听 , 用 b u s . on来监听,用bus. on来监听,用bus.emit来发送
<script type="text/javascript">
window.onload = function () {
var bus = new Vue();//中央事件总线
Vue.component("weixinauthor",{
template:`<div>
<input type="text" ref = "mytext">
<button @click="handclick">发布</button>
</div>`,
methods:{
handclick(){
bus.$emit("weixinmessage",this.$refs.mytext.value);
}
}
})
Vue.component("weixinuser",{
//用bus.$on订阅
template:`<div style="background-color: yellow">
我是一个微信用户
</div>`,
mounted(){//在当前组件dom创建完就会调用
bus.$on("weixinmessage",(data)=>{
console.log("收到推送",data)
})
}
})
const vm = new Vue({
el:'#app',
data:{
},
})
}
</script>
</head>
<body>
<div id="app">
<weixinauthor></weixinauthor>
<weixinuser></weixinuser>
</div>
</body>
六、动态组件
- < compontent>元素,动态地绑定多个组件到它的is属性
- < keep-alive> 保留状态,避免重新渲染
<script type="text/javascript">
window.onload = function () {
const vm = new Vue({
el:'#app',
data:{
who:'home'
},
methods:{
},
components:{
"home":{
template:`<div><input type="text">home</div>`
},
"list":{
template:`<div>list</div>`
},
"shopcar":{
template:`<div>shopcar</div>`
}
}
})
}
</script>
</head>
<body>
<div id="app">
<keep-alive>
<component :is = "who"></component>
</keep-alive>
<footer>
<ul>
<li @click="who = 'home'"><a href="#">首页</a></li>
<li @click="who = 'list'"><a href="#">列页表</a></li>
<li @click="who = 'shopcar'"><a href="#">购物车页面</a></li>
</ul>
</footer>
</div>
</body>
显示结果:
- 来回切换后,input中的内容不变
七、组件的插槽slot
- slot:插槽用于决定将所携带的内容,插入到指定的某个位置,从而使模板分块,具有模块化的特质和更大的重用性。
<script type="text/javascript">
window.onload = function () {
Vue.component("child",{
template:`<div>
<slot></slot>
child
</div>`
})
const vm = new Vue({
el:'#app',
data:{
},
})
}
</script>
</head>
<body>
<div id="app">
<child><div>aaaaaaaaaa</div></child>
</div>
</body>
结果显示:
具名slot:可以将组将插到指定的位置
- 用slot来命名
- 用name来声明
<script type="text/javascript">
window.onload = function () {
Vue.component("child",{
template:`<div>
<slot name = "a"></slot>
child
<slot name = "b"></slot>
</div>`
})
const vm = new Vue({
el:'#app',
data:{
},
})
}
</script>
</head>
<body>
<div id="app">
<child>
<div slot="a">aaaaaaaaaa</div>
<div slot="b">bbbbbbbbbb</div>
</child>
</div>
</body>
结果显示: