文章目录
前言VUE里组件是什么?
-
组件 (Component) 是 Vue.js 最强大的功能之一
-
组件可以扩展 HTML 元素,封装可重用的代码
-
说白了就是可以自定义标签。将能实现完整功能的html标签组合起来,用一个自定义的新标签实现这个功能
一、组件注册
1.全局组件
Vue.component(‘组件名称’, { }),第 1 个参数是标签名称,第 2 个参数是一个选项对象
全局组件注册后,任何vue实例都可以用
<div id="app">
<!-- 2、组件使用组件名称是以 HTML 标签的形式使用 -->
<my-component></my-component>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
// 1、my-component 就是组件中自定义的标签名
Vue.component('my-component', {
父组件传值的接收属性:字符串,数组,对象都可以,常用为对象,根据需求使用
props:{
name:{
type:number or string or object // 设置接收类型是什么
required:true //设置是否是必传项
}
}
//模板
template: '<div>hello world</div>'
// data 注意 data数据必须函数,并且要求返回一个对象
data(){
return{
数据1:1,
数据2:2
}
}
//方法
methods:{
}
});
const vm = new Vue({
el: '#app',
});
</script>
2.局部组件(私有组件)
- 只能在当前注册它的 vue 实例中使用
<div id="app">
<my-component></my-component>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
new Vue({
el: '#app',
// 局部注册组件
components: {
//组件名
MyComponent:{
template: '<div> A custom component! </div>'
}
});
</script>
3.组件注意事项
1.template模板中只能有一个根元素
2.data的值是一个函数
3. 定义组件时,可以用大驼峰,也可以用-隔开单词
-结论: HelloWorld => hello-world hello-world => hello-world
注意在dom中使用组件必须使用短横线命名法,
在定义组件和引用组件时使用驼峰命名法或者短横线命名法都可以,
不区分大小驼峰,因为vue对大小写不敏感
组件嵌套时,如果使用驼峰式命名组件,
那么在使用组件的时候,
只能在字符串模板中用驼峰的方式使用组件,
4.标签也可以使用单边标签,但是就不会传内容了,也就是不能用插槽了
二、组件之间传值
1.父组件向子组件传值
父组件向子组件传值得本质 叫自定义属性
- 在子组件标签上设置自定义属性,
接收父组件的数据,在子组件内部通过props属性接收- 在 props 中使用驼峰形式,模板中需要使用短横线的形式使用,字符串形式的模板中没有这个限制
- 在父组件中定义一个数据
- 在子组件标签上通过b-bind自定义一个属性名,值为父组件中的数据
- 子组件中通过成员props来接收,它的值是一个数组,组数的值是上面自定义的属性名。
- 在子组件模板中就可以使用这个props中传过来的值了
<div id="app">
<!-- 2.通过b-bind自定义一个属性名,值为父组件中的数据 -->
<login-demo :demo="FatherMsg"></login-demo>
</div>
<script src="/vue.js"></script>
<script>
let vm = new Vue({
el: "#app",
data: {
// 1.定义父组件要传的数据
FatherMsg: "这是父组件上的数据",
},
components: {
loginDemo: {
// 3.通过props成员来接收,值是个数组,数组里的数据是上面的自定义属性名
props: ["demo"],
// 4.在组件模板上使用这个props传进来的值
template: `<div>这是登录组件demo--{{demo}}</div>`,
},
},
});
</script>
2.子组件向父组件传值
- 子组件用
$emit()
触发事件$emit()
第一个参数为自定义的事件名称,第二个参数为需要传递的数据- 父组件用 v-on 监听子组件的事件
<div id="app">
子组件传来的数据:{{fromsondata}}
<!-- 3.在dom中使用这个组件时,绑定这个自定义事件,引用父组件的方法 -->
<reg-demo @fun="show"></reg-demo>
</div>
<script src="/vue.js"></script>
<script>
let vm = new Vue({
el: "#app",
data: {
fromsondata: "",
},
methods: {
// 4父组件定义的方法,父组件接收子组件的数据
show(data) {
console.log(data);
this.fromsondata = data;
},
},
components: {
regDemo: {
// 1.在子组件标签模板里绑定一个事件 display
template: `<div>这是一个注册组件<button @click="display">发送</button></div>`,
data() {
return {
// 定义需要传递的参数
sondata: "子组件数据",
};
},
methods: {
// 2.引用事件 ps:在这个事件方法里 发射 $emit()第1个参数为自定义事件名称,第二个参数为需要传递的数据
display() {
this.$emit("fun", this.sondata);
},
},
},
},
});
</script>
3.兄弟之间的传递(eventBus)
兄弟传值,爷传孙子,祖先传后代… 最优解决方案:vuex
兄弟传值: 中介 eventBus
提供事件中心
三、组件插槽
1.匿名插槽
插槽的作用:父组件向子组件传 “内容”
有时候子组件的结构也不确定,父组件向子组件传结构
<body>
<div id="app"> // ↓插槽数据
<my-son><h3 style="color:red;">给我一根烟</h3></my-son>
</div>
</body>
<script src="./lib/vue.js"></script>
<script>
var vm = new Vue({
el:"#app",
data:{
},
components:{
"MySon":{ //给slot标签
template:"<div>我是子组件: <slot>我有一本书</slot></div>",
}
}
})
</script>
2.具名插槽
具名插槽如果使用v-slot 则需要在外层包裹template标签,
<!-- <template slot="header"> 这个是废弃写法
<h1>这是主标题</h1> 可以直接学新版写法
<h3>这是副标题</h3>
</template> -->
<template v-slot:header>
<h1>这是主标题</h1>
<h3>这是副标题</h3>
</template>
<p>这是内容</p>
<template v-slot:footer>
<h5>这是底部</h5>
</template>
</my-son>
</div>
3.作用域插槽
<body>
<div id="app">
<fruit-list :msg="fruits">
<!-- <template slot-scope="slotProps">
<strong :class="slotProps.info.id==id?'current':''">{{slotProps.info.name}}</strong>
</template> -->
<!-- 作用域插槽新语法: -->
<!-- <template v-slot:default="slotProps">
<strong :class="slotProps.info.id==id?'current':''">{{slotProps.info.name}}</strong>
</template> -->
<!-- 解构赋值 -->
<template v-slot:default="{aaa}">
<strong :class="aaa.id==id?'current':''">{{aaa.name}}</strong>
</template>
</fruit-list>
</div>
</body>
<script src="./lib/vue.js"></script>
<script>
//作用域插槽: 在父组件中对子组件进行加工处理
// 需求:根据父组件中id的数据,让对应的水果字体加粗变黄
//
var vm = new Vue({
el: "#app",
data: {
id:1,
fruits: [
{ id: 1, name: "apple" },
{ id: 2, name: "orange" },
{ id: 3, name: "banana" }
]
},
components: {
"FruitList": {
template: `<div>
<ul>
<li v-for="(item,index) in msg" :key="item.id">
<slot :aaa="item"></slot>
</li>
</ul>
</div>`,
props:{
msg:{
required:true,
type:Array
}
}
}
}
})
var {name,age} = {
name:"jack",
age:18
}