vue组件通信
组件间关系
组件 间 嵌套 使用 形成 一下 几种关系 父子、兄弟(祖先后代)
组件间通信
父向子通信
通过props
1,props值是一个 数组
// properties 缩写
let CommonHead = {
props:["title"],
template:`
<h1>
{{ title }}
</h1>
`
}
let Home = {
template:`
<div>
我是首页
<common-head title="我是首页"/>
</div>
`,
components:{
CommonHead
}
}
<body>
<div id="app">
<home></home>
<news></news>
</div>
<script src="../vue.js"></script>
<script>
//properties 缩写
let CommonHead = {
props: ["title"],
template:
`
<h1>
{{ title }}
<!--
<button @click="title='我改变了数据'">按钮</button>
-->
</h1>
`
}
let Home = {
template: `
<div>
我是首页
<common-head title="我是首页"/>
</div>
`,
components: {
CommonHead
}
}
let News = {
template: `
<div>
我是新闻页
<common-head :title="msg"/>
</div>
`,
data() {
return {
msg: "我是新闻页"
}
},
components: {
CommonHead
}
}
Vue.component("Home", Home);
Vue.component("News", News);
// 挂载 (挂载到Vue,全局组件、或者到另一个组件中)
// 组件名 推荐使用大驼峰(或者下划线、common-head),使用时使用下划线(自动解析)
let vm = new Vue({
el: "#app"
})
</script>
</body>
props验证
props是一个对象,不再是一个数组
props:{
title:{
type:String,
required:true
},
title2:String,
title3:{
type:Number,
default:0
}
}
类型:
String
Number
Boolean
Array
Object
Date
Function
Symbol
// properties 缩写
let CommonHead = {
//此时的props不是一个数组 而是一个对象
props: {
title: {
type: String,
required: true
},
title2: {
type: String,
default: '我是首页'
},
arr: {
type: Array,
default: () => [1, 2, 3] //要求出入构造函数 返回一个值
}
},
template: `
<h1>
{{ title }}
{{title2}}
<ul>
<li v-for="(item,index) in arr" :key="index">
{{item}}
</li>
</ul>
</h1>
`
}
-
注意:
-
1,props命名 不能 和data或者 计算属性 重名(否则互相影响)
-
2,props 值 不能在 子组件 内部修改 (只能由传入放修改 props单向数据流)
//只能由传入放修改 props单向数据流
let Home = {
template: `
<div>
我是首页
<common-head title="我是首页"/>
</div>
`,
components: {
CommonHead
}
}//props 值 不能在 子组件 内部修改
//修改之后(button)也不会报错 会警告 单项数据流 修改之后不易于维护
let CommonHead = {
props: ["title"],
template:
`
<h1>
{{ title }}
<!--
<button @click="title='我改变了数据'">按钮</button>
-->
</h1>
`
} -
3,props验证中:如果数据类型是 数组或者 对象,要求 默认值是 一个函数返回这个默认值
arr: {
type: Array,
default: () => [1, 2, 3] //要求出入构造函数 返回一个值
}
子向父通信:
-
自定义事件
子组件中 this.$emit("事件名",携带的参数)
父组件中接收
<body>
<div id="app">
<home></home>
</div>
<script src="../vue.js"></script>
<script>
// properties 缩写
let CommonHead = {
template: `
<div>
<h1>子组件</h1>
<button @click="biubiubiu">发射</button>
</div>
`,
data() {
return {
msg: "我是子组件的数据"
}
},
methods: {
//子组件中 this.$emit("事件名",携带的参数)
biubiubiu() {
this.$emit("a", this.msg);
}
}
}
let Home = {
template: `
<div>
父组件
<common-head @a="receive"/>
{{ msg }}
</div>
`,
data() {
return {
msg: "哈哈哈"
}
},
methods: {
receive(msg) {
alert("事件传递过来啦");
this.msg = msg;
}
},
components: {
CommonHead
}
}
Vue.component("Home", Home);
let vm = new Vue({
el: "#app"
})
</script>
</body>
组件的第二种分类:
容器组件 (业务逻辑 处理数据)
傻瓜组件 (展示、接受数据)
状态提升:将数据处理 提升到 父组件中
组件通信 之 兄弟之间 通信
event bus 事件中心总线
原理:新建一个空的 第三方的vue 实例
由实例 触发自定义事件 由实例来 接收自定义事件
实例.$emit()
实例.$on("事件名",()=>{
})
let bus = new Vue();
在a组件中
调用 bus.$emit("事件名",数据)
在b组件中
找到bus
bus.$on("事件名",callback)
<body>
<div id="app">
<home></home>
</div>
<script src="../vue.js"></script>
<script>
let bus = new Vue();
// properties 缩写
let CommonHead = {
template: `
<div>
<h1>子组件</h1>
<button @click="biubiubiu">发射</button>
</div>
`,
data() {
return {
msg: "我是子组件的数据"
}
},
methods: {
biubiubiu() {
bus.$emit("a", this.msg);
}
}
}
let Child2 = {
template: `
<div>
<h1>我是另一个子组件</h1>
{{msg}}
</div>
`,
data() {
return {
msg: "我是另一个子组件的数据"
}
},
mounted() {
/* bus.$on("a",function(msg){
this.msg = msg;
}.bind(this)) */
/* bus.$on("a",(msg)=>{
this.msg = msg;
}) */
let _this = this;
bus.$on("a", function (msg) {
_this.msg = msg;
})
}
}
let Home = {
template: `
<div>
父组件
<common-head></common-head>
<child2/>
{{ msg }}
</div>
`,
data() {
return {
msg: ""
}
},
components: {
CommonHead,
Child2
}
}
Vue.component("Home", Home);
let vm = new Vue({
el: "#app"
})
</script>
</body>
<body>
<div id="app">
<common-head></common-head>
</div>
<script src="../vue.js"></script>
<script>
//定义组件
let CommonHead = {
template: `
<div>
<h1>我是公共的头部</h1>
</div>
`,
}
//全局组件
Vue.component("CommonHead", CommonHead)
let vm = new Vue({
el: "#app"
})
</script>
</body>
-
局部组件
{
template,
data(){},
methods: {},
components: {
Home: Home
}
}<body>
<div id="app">
<common-head></common-head>
</div>
<script src="../vue.js"></script>
<script>
let Child = {
template:
`
<h5>我是一个子组件</h5>
`
}
let CommonHead = {
template: `
<div>
<h1>我是公共的头部</h1>
<child></child>
</div>
`,
components: {
Child
}
}
let vm = new Vue({
el: "#app",
components: {
CommonHead
}
})
</script>
</body>
-
注意:
-
组件 也是 Vue的实例(vm上有的属性和语法、组件都有)
-
组件的data属性 必须是一个函数 返回一个对象
data(){
return {
msg:"我是组件内的"
}
}, -
组件 template 有且只能有一个根元素
template: `
<div>
<h1>我是公共的头部</h1>
<child></child>
</div>
`,
-
以下三种仅供面试用
1,ref
let CommonHead = {
template:`
<div>
<h1>子组件</h1>
{{ msg }}
</div>
`,
data(){
return {
msg:"我是子组件的数据"
}
}
}
let Home = {
template:`
<div>
父组件
<common-head ref="child"/>
<button @click="change">按钮</button>
</div>
`,
data(){
return {
msg:""
}
},
mounted(){
},
methods:{
change(){
console.log( this.$refs )
let childComponent = this.$refs['child'];
childComponent.msg = "哈哈哈哈"
}
},
components:{
CommonHead
}
}
Vue.component("Home",Home);
let vm = new Vue({
el:"#app"
})
注意: 不推荐使用,破坏了单向数据流
2.$parent $children
谨慎使用 理由同上
3,provide inject
**以上2个千万不要要 第三个偶尔用用**
3,provide inject
<body>
<div id="app">
<home></home>
</div>
<script src="./vue.js"></script>
<script>
// properties 缩写
let CommonHead = {
//子组件接收
inject: ['arrData'],
template: `
<div>
<h1>子组件</h1>
{{ msg }}
</div>
`,
data() {
return {
msg: "我是子组件的数据"
}
},
mounted() {
console.log(this.arrData);
console.log(this.$parent)
setTimeout(() => {
this.$parent.msg = "子组件改变了你"
}, 2000)
}
}
var arr = [1, 2, 3, 4, 5];
let Home = {
template: `
<div>
父组件
<common-head ref="child"/>
<button @click="change">按钮</button>
{{msg}}
</div>
`,
//父组件提供数据
provide: { //我这个组件 提供了 一个数据 key arrData,我的子组件 可以 去拿我提供的这个数据
arrData: arr,
b: 2
},
data() {
return {
msg: "我是父组件的"
}
},
mounted() {
console.log(this.$children)
},
methods: {
change() {
console.log(this.$refs)
let childComponent = this.$refs['child'];
childComponent.msg = "哈哈哈哈"
}
},
components: {
CommonHead
}
}
Vue.component("Home", Home);
let vm = new Vue({
el: "#app"
})
</script>
</body>