组件注册:
注册语法(全局注册):全局组件注册后,任何vue实例都可以用
Vue.component('组件名称', {
data: 组件数据,
template: 组件模板内容
})
定义一个名为button-counter例子:
<script type="text/javascript">
Vue.component('button-counter',{ //第一个参数是组件名称 vue.component是api
data:function(){ //第二个参数是一个对象 第一个属性一个属性是data:值必须是一个函数,同时这个函数要求返回一个对 象,函数里提供具体的对象,放需要的数据 如果不需要数据 可以省略data这个属性
return {
count:0
}
},
template:'<button @click="handle">点击{{count}}次</button>', //第二个属性是模板内容 内容是‘字符串 vue支持的模板语法’ 绑定的事件要双引号,因为外面是单引号
methods: {
handle:function(){
this.count += 2; //count++
}
}
})
var vm = new Vue({ //vue实例也是一个组件 顶层组件
el:'#app',
data: {
}
})
</script>
组件用法:
<div id="app">
<!-- 用组件的名称放到容器里来使用组件 因为在app里面所以也是子组件-->
<button-counter></button-counter>
</div>
注册注意事项:
- data必须是函数 VUE实例data是对象 本质也是组件. 组件都是一个独立的实例, 函数会形成闭包 每个组件拥有独立的数据
- 组件模板内容必须是单个根元素 必要情况下可以最外面加div盒子
- 组件模板内容可以是模板字符串复杂的情况下 用字符串 反引号··(需要浏览器的支持,因为是es6语法)
- 如果使用驼峰式命名组件,那么在使用组件的时候,只能在字符串模板中用驼峰的方式使用组件,但是
在普通的标签模板中,必须使用短横线的方式使用组件,因为不识别大小写.
局部注册:只能在当前注册它的vue实例(父组件)中使用
var Child = {
template: '<div>hello</div>'
}
var vm = new Vue({
el:""
components: {
'my-component':Child //components注册局部组件
}
})
Vue组件之间传值
父组件向子组件传值
- 父组件发送的形式是以属性的形式绑定值到子组件身上。
- 然后子组件用属性props接收 props传递数据类型:单向数据流
- 属性命名:在props中使用驼峰形式,标签模板中需要使用短横线的形式,字符串形式的模板中没有这个限制
- 属性值类型:基本类型字符串数字布尔 要用v-bind绑定 如果不用v-bind就都是字符串类型了 还有复杂类型数组和对象.
父组件通过属性将值传递给子组件
<div id="app">
<div>{{pmsg}}</div>
<!-- 给子组件传入一个静态的值 -->
<menu-item title='来自父组件的值'></menu-item>
<!-- 2、 需要动态的数据的时候 需要属性绑定的形式设置 此时 ptitle 来自父组件data 中的数据 .
传的值可以是数字、对象、数组等等
-->
<menu-item :title='ptitle' content='hello'></menu-item>
</div>
<script type="text/javascript">
Vue.component('menu-item', {
// 子组件用属性props **接收** 父组件传递过来的数据 props是个数组
props: ['title', 'content'],
data: function() {
return {
msg: '子组件本身的数据'
}
},
template: '<div>{{msg + "----" + title + "-----" + content}}</div>' //接受数据后就能在模板上使用数据
});
var vm = new Vue({
el: '#app',
data: {
pmsg: '父组件中内容',
ptitle: '动态绑定属性'
}
});
</script>
子组件向父组件传值
- 子组件用$emit()触发事件
- $emit() 第一个参数为 自定义的事件名称 第二个参数为需要传递的数据
- 父组件用v-on 监听子组件的事件
- props是单向数据流,只能父组件向子组件传值,而不允许子组件直接操作父组件的数据.
子组件通过自定义事件向父组件传递信息
Vue.component('menu-item', {
props: ['parr'],
template: `
<div>
<button @click='$emit("enlarge-text", 5)'> </button>
</div>
`
});
// 子传父,一定要定义一个@click=“函数1” 子传父一定是一个自定义事件 子组件触发一个事件 父组件去监听这个事件 子组件触发了 父组件就接收到了
//函数体内,代码片段要写$emit('自己取的事件名',子组件内的参数) 事件名是要被父组件监听的
//在父组件模板里 @事件名=“函数2($event)” $event接收的是子组件内的参数
父组件监听子组件的事件
<menu-item :parr='parr' @enlarge-text='handle($event)'></menu-item>
兄弟之间的传递
- 兄弟之间传递数据需要借助于事件中心,通过事件中心传递数据
- 提供事件中心 var hub = new Vue()
- 传递数据方,通过一个事件触发hub.$emit(方法名,传递的数据)
- 接收数据方,通过mounted(){} 钩子中 触发hub.$on()方法名
- 销毁事件 通过hub.$off()方法名销毁之后无法进行传递数据
Ref
ref 被用来给DOM元素或子组件注册引用信息。引用信息会根据父组件的 $refs 对象进行注册。如果在普通的DOM元素上使用,引用信息就是元素; 如果用在子组件上,引用信息就是组件实例
注意:只要想要在Vue中直接操作DOM元素,就必须用ref属性进行注册
子传父简单办法:
在子组件标签上添加ref='name'
属性,父组件实例中添加$refs属性就可以访问到data数据了
<div id="app">
<my-com ref="com1"></my-com>
</div>
<template id="tem">
<div>
<h1>我是组件1</h1>
</div>
</template>
<script>
Vue.component('myCom',{
template:"#tem",
data(){
return {
name:'你抓到我了么???'
}
}
})
const vm = new Vue({
el:'#app',
mounted() {
console.log(this.$refs.com1.name);
}
})
</script>
父传子简单方法:
$parent:子组件可以直接获取到该子组件的父组件的实例对象
<div id="app">
<my-com></my-com>
</div>
<template id="tem">
<div>
<h1>我要在子组件中显示一下父组件的msg : {{ $parent.msg }}</h1>
</div>
</template>
<script>
Vue.component('myCom',{
template:"#tem",
mounted(){
// $parent 可以让子组件 直接获取到 改子组件的父组件实例对象
console.log(this.$parent.msg) //直接拿到父组件的msg属性了
}
})
const vm = new Vue({
el:'#app',
data:{
msg:'我是父组件'
}
})
</script>
组件插槽
- 组件的最大特性就是复用性,而用好插槽能大大提高组件的可复用能力
- 正常情况下,
<Child><span style=”color:red;”>hello world</span></Child>
在组件标签Child中的span标签会被组件模板template内容替换掉,当想让组件标签Child中内容传递给组件时需要使用slot插槽; - 通俗讲就是“占坑”,在组件模板中占好了位置,当使用该组件标签时候,组件标签里面的内容就会自动填坑(替换组件模板中位置),当插槽也就是坑有命名时,组件标签中使用属性slot=”mySlot”的元素就会替换该对应位置内容
匿名插槽
<div id="app">
<!-- 这里的所有组件标签中嵌套的内容会替换掉slot 如果不传值 则使用 slot 中的默认值 -->
<alert-box>有bug发生</alert-box>
<alert-box>有一个警告</alert-box>
<alert-box></alert-box>
</div>
Vue.component('alert-box', {
template: `
<div>
<strong>ERROR:</strong>
//当组件渲染的时候,这个 <slot> 元素将会被替换为“组件标签中嵌套的内容”。
// 插槽内可以包含任何模板代码,包括 HTML
<slot>默认内容</slot>
</div>
`
});
具名插槽
- 具有名字的插槽
- 使用 < slot> 中的 “name” 属性绑定元素
- 具名插槽的渲染顺序,完全取决于模板,而不是取决于父组件中元素的顺序
- 通过slot属性来指定, 这个slot的值必须和下面slot组件得name值对应上如果没有匹配到 则放到匿名的插槽中
- < template>< /template>适用的场景是 多条文本填充到插槽中,也就是插槽中有多个标签插槽名字标注到标签上 只能有一个
作用域插槽
- 父组件对子组件加工处理
- 既可以复用子组件的slot,又可以使slot内容不一致