组件
组件系统是 Vue 的另一个重要概念,因为它是一种抽象,允许我们使用小型、独立和通常可复用的组件构建大型应用。仔细想想,几乎任意类型的应用界面都可以抽象为一个组件树
- 创建组件的两种方式:1 全局组件 2 局部组件
全局组件
- 说明:全局组件在所有的vue实例中都可以使用
- 注意:先初始化根实例再注册组件
- 注意:组件中的
data
必须是函数
<div id="app">
<!-- 使用自定义元素的方式 -->
<!-- 使用组件 -->
<my-component></my-component>
</div>
<!-- 引入vue -->
<script src="./vue.js"></script>
<script>
// 创建全局组件 不能放在 new Vue 的下面 否者会报错
// 第一个参数:表示组件名称
// 第二个参数:表示组件的配置对象
Vue.component('my-component', {
// 指定组件中展示的HTML内容
// 注意:组件的模版中必须有唯一的根元素,否则,会报错
// template: '指定需要展示的内容',
// ES6: 字符串模板 通过 反引号 使用
template: `
<div>
<p>我是全局组件 </P>
<div v-color>内容 --- {{ msg }} --- {{ num }}</div>
<button @click="fn">组件触发事件</button>
</div>
`,
data() {
return {
msg: '注意:组件的data必须是一个函数!!!',
num:100
}
},
// 用来设置模板中的事件
methods:{
fn(){
this.num += 1
}
},
// 自定义属性
directives:{
color(el){
el.style.color='red'
}
}
});
// 关联到页面中 (组件要渲染的地方)
var vm = new Vue({
el: '#app',
data: {
}
})
// ===> 渲染结果
请看下面的这张图片
</script>
局部组件
- 说明:局部组件,是在某一个具体的vue实例中定义的,只能在这个vue实例中使用
<div id="app">
<hello></hello>
</div>
<script src="./vue.js"></script>
<script>
// 创建 vue 实例
var vm = new Vue({
el: '#app',
data: {
},
// 创建局部组件
components: {
// hello 表示组件名称
// 对象表示该组件的配置对象
hello: {
template: ` <h1>局部组件</h1>`
}
}
});
组件通讯
父组件到子组件
- 方式:通过
props
属性来传递数据 - 注意:属性的值必须在组件中通过
props
属性显示指定,否则,不会生效 - 说明:传递过来的
props
属性的用法与data
属性的用法相同
<div id="app">
<child :msg='parentProp'></child>
</div>
<script src="./vue.js"></script>
<script>
var vm = new Vue({
el: '#app',
data: {
parentProp:'父组建中的属性'
},
// 创建局部组件
components:{
// 子组件
child:{
// props 监听父组件传递过来的信息
props:['msg'],
// 传递过来后,可在 template 模板里直接引用,就如已经传递过来数据塞到data
template:`<h1>{{ msg }}</h1>`
}
}
})
</script>
子组件到父组件
- 方式:父组件给子组件传递一个函数,由子组件调用这个函数
- 说明:借助vue中的自定义事件(v-on:cunstomFn="fn")
-
$emit()
:触发事件
<div id="app">
<h1>父组件: 这是子组件传递过来的数据 -----{{ msg }} </h1>
<!-- 此处的方法 pfn 就是父组件中提供的属性 -->
<child v-on:pfn='parentFn'></child>
</div>
<script src="./vue.js"></script>
<script>
// 子组件传递数据给父组件
// 1 由父组件提供一个方法
// 2 这个方法需要让子组件来调用
// 3 在子组件中调用父组件的方法 ,将要传递的数据作为 父组件方法的参数
// 进行传递
var vm = new Vue({
el: '#app',
data: {
msg :''
},
methods:{
parentFn(arg){
console.log(arg)
this.msg = arg
}
},
// 创建组件
components : {
// 子组件
child :{
template :`
<button @click="test">子组件传递数据给父组件</button>`,
methods: {
// 子组件:通过$emit调用
test(){
this.$emit('pfn','这是数据')
}
}
}
}
})
</script>
另外的一种情况是当父组件和子组件都有一个独立的文件时候怎么实现通讯呢?
- 三个步骤:
1.在父组件中引入子组件
// 导入 numberbox 组件
import NumberBox from '../common/NumberBox.vue'
2.在父组件export default{
//里面 导入 components: { NumberBox }
}
3.在父组件中创建一个 <NumberBox ></NumberBox>标签,这个标签用来存放子组件的内容
非父子组件通讯
在简单的场景下,可以使用一个空的 Vue 实例作为事件总线
-
$on()
:绑定事件
var bus = new Vue()
// 触发组件 A 中的事件
bus.$emit('id-selected', 1)
// 在组件 B 创建的钩子中监听事件
bus.$on('id-selected', function (id) {
// ...
})
- 示例:组件A ---> 组件B
<div id="app">
<comb></comb>
<coma></coma>
</div>
<script src="./vue.js"></script>
<script>
// a组件 传递数据给 b组件
// 也就是:b组件注册事件,由a组件触发这个事件
// 创建一个空的Vue实例对象,
var bus = new Vue()
var vm = new Vue({
el: '#app',
components: {
// b组件
comb: {
template: '<h1>这是 B组件 --- {{ msg }}</h1>',
data() {
return {
msg: ''
}
},
created() {
// 绑定事件
bus.$on('fn', (arg) => {
console.log(arg);
this.msg = arg
})
}
},
// a组件
coma: {
template: `<button @click="send">A组件的按钮</button>`,
methods: {
send() {
bus.$emit('fn', '这是a传递给b的数据')
}
}
}
}
})
</script>