目录
1.组件机制
1.1含义
组件 (Component) 是 Vue.js 最强大的功能之一。组件可以扩展HTML元素,封装可重用的代码。
1.2特点
- 组件是可以进行任意次数的复用。
- 组件的data必须是一个函数,确保每个实例可以维护一份被返回对象的独立的拷贝,也就是任何一个组件的改变不会影响到其它组件。
2.组件注册
2.1全局注册
可以使用Vue.component(tagName, options) 注册一个全局组件, 注册之后可以用在任何新创建的 Vue 根实例的模板中使用。
<script src="https://cdn.jsdelivr.net/npm/vue@2.7.10/dist/vue.js"></script>
<div id="app">
<!-- 3.组件使用 -->
<my-a></my-a>
<my-b></my-b>
</div>
<script>
// 1.定义组件配置对象
let myA={
template:`
<div>
{{msgA}}
</div>
`,
data(){
return {
msgA:'我是子组件'
}
}
};
let myB={
template:`
<div>B组件
------------------
<my-a></my-a>
</div>
`
}
// 2.注册组件
// 1.全局注册 --任意组件里面使用
Vue.component('my-a',myA);
Vue.component('my-b',myB);
new Vue({
el:"#app",
data:{
msg:'我是父组件'
},
methods:{
}
})
</script>
2.2局部注册
全局注册往往是不够理想的。比如,如果你使用一个像 webpack 这样的构建系统,全局注册所有的组件意味着即便你已经不再使用一个组件了,它仍然会被包含在你最终的构建结果中。这造成了用户下载的 JavaScript 的无谓的增加。局部注册的组件只能在当前组件中使用。
<script src="https://cdn.jsdelivr.net/npm/vue@2.7.10/dist/vue.js"></script>
<div id="app">
<my-a></my-a>
<my-b></my-b>
</div>
<script>
// 1.定义组件配置对象
let myA = {
template: `
<div>
{{msgA}}
</div>
`,
data() {
return {
msgA: '我是子组件'
}
}
};
let myB = {
components: {
'my-a': myA
},
template: `
<div>B组件
------------------
<my-a></my-a>
</div>
`
}
new Vue({
// 2.局部注册 --只能在根组件使用
components: {
'my-a': myA,
'my-b': myB
},
el: "#app",
data: {
msg: '我是父组件'
},
methods: {
}
})
</script>
3.组件传值
3.1父组件给子组件传值
- 将传递的数据写入子组件。
- 在子组件内使用props接收数据。
3.11静态传值
<div id="app">
<my-a msg1="我是静态传递"></my-a>
</div>
<script>
let myA = {
props: ['msg1'],
template: `
<div>
我是子组件----
{{msg}}
</div>
`
}
new Vue({
components: {
'my-a': myA
},
el: '#app',
data: {
msg: '我是父组件'
}
})
</script>
3.12动态传值
<div id="app">
<my-a :obj="'我是动态传递'"></my-a>
</div>
<script>
let myA = {
props: ['obj'],
template: `
<div>
我是子组件----
{{obj}}
</div>
`
}
new Vue({
components: {
'my-a': myA
},
el: '#app',
data: {
msg: '我是父组件'
}
})
</script>
3.13类型校验
validator:对数值进行校验。
<div id="app">
<my-a :age="18" :obj="{name:'zhangsan'}" :stu='[1,2,3]' :sub1="undefined" :sub="null"></my-a>
</div>
<script>
let myA = {
props: {
age: {
// 可以进行多个类型值得校验
type: [Number, String, Boolean],
// 自定义校验器规则 小于50就对
validator(val) {
return val < 50
}
},
sub: String,
obj: Object,
sub1: Number,
stu: {
type: Array,
// 默认值 错误
// default:[4,5,6]
default() {
return [4, 5, 6]
}
}
},
template: `
<div>
我是子组件----
{{age}}
{{obj}}
{{stu}}
{{sub}}
{{sub1}}
</div>
`
}
new Vue({
components: {
'my-a': myA
},
el: '#app',
data: {
msg: '我是父组件'
}
})
</script>
3.2子组件给父组件传值
- 在子组件内发射自定义事件 $emit('自定义事件名称',传递的数据)
- 在子组件标签上使用自定义事件来接受 @自定义事件='handler'
handler(a){}
<div id="app">
<!-- 在父组件使用子组件的标签定义自定义事件 -->
<my-a @my-event="handler"></my-a>
</div>
<script>
let myA = {
template: `
<div>
我是子组件
<button @click='toSend'>子组件传值给父组件</button>
</div>
`,
data() {
return {
subMsg: '我是子组件A --我要给父组件传值'
}
},
methods: {
toSend() {
this.$emit('my-event', this.subMsg)
}
}
}
new Vue({
components: {
'my-a': myA
},
el: "#app",
data: {
msg: '我是父组件'
},
methods: {
handler(a) {
console.log(a, '这是子组件的值');
}
},
})
</script>
4.兄弟组件传值
- 定义一个事件总线 new Vue()
- 引入事件总线,使用事件总线Bus.$emit(事件名称,发送的数据)
- 另一页面,引入事件总线,使用事件总线Bus.$son(事件名称,(a)=>{a ---->收到数据})
事件总线
import Vue from 'vue';
export default new Vue();
Header.vue页面
<template>
<div>
{{ msgH }}
<button @click="handler">传值给Footer</button>
</div>
</template>
<script>
//引入事件总线
import Bus from "../eventBus.js";
console.log(Bus, "事件总线");
export default {
data() {
return {
msgH: "头部组件",
Footer: "这是兄弟组件Footer",
};
},
methods: {
handler() {
// 兄弟组件传值
// 1.兄弟组件使用$emit 发射事件 携带参数
Bus.$emit("toFoot", this.Footer);
},
},
};
</script>
Footer.vue页面
<template>
<div>
{{ msgF }}
</div>
</template>
<script>
// 引入事件总线
import Bus from "../eventBus.js";
export default {
data() {
return {
msgF: "底部组件",
};
},
created() {
//('事件名称' 收到的数据)
Bus.$on("toFoot", (a) => {
console.log(a, "这是Footer传给我的值");
});
},
};
</script>
5.祖先与子孙组件之间的传值
5.1祖先向子孙组件传值
App.vue页面
<template>
<div id="app">
<img alt="Vue logo" src="./assets/logo.png" />
<Header></Header>
<hr />
<Footer>
<!-- 根组件的孙子组件 -->
<FooterChild></FooterChild>
</Footer>
</div>
</template>
<script>
import Header from "./components/Header.vue";
import Footer from "./components/Footer.vue";
export default {
name: "App",
components: {
Header,
Footer,
},
data() {
return {
msg: "我是祖先组件",
a:13
};
},
// 祖先组件使用provide方法提供传递的数据
provide() {
return {
msg: this.msg,
a: this.a,
};
},
};
</script>
FooterChild.vue
<template>
<div>
{{ msg }}---{{ a }}
</div>
</template>
<script>
export default {
data() {
return {
msgC: "底部组件的子组件",
};
},
// 注入数据
inject: ["msg", "a"],
};
</script>
5.2单向数据绑定
Footer.vue
<template>
<div>
{{ msgF }}
<FooterChild :age="age" />
{{ age }}
<button @click="age = 18">点击我修改age</button>
</div>
</template>
<script>
import Bus from "../eventBus.js";
import FooterChild from "./FooterChild.vue";
export default {
components: {
FooterChild,
},
data() {
return {
msgF: "底部组件",
age: 15,
};
},
created() {
// {prototype:$emit() $on()}
Bus.$on("toFoot", (a) => {
console.log(a, "这是Footer传给我得值");
});
},
};
</script>
FooterChild.vue
<template>
<div>
{{ msgC }}-{{ msg }}--{{ a }}--{{ age }}
<button @click="age = 250">点击我修改age</button>
</div>
</template>
<script>
export default {
data() {
return {
msgC: "底部组件的子组件",
};
},
// 注入数据
inject: ["msg", "a"],
// 给父组件传递age数值
props: ["age"],
};
</script>