vue组件中常见的传值方式
一.父传子
基本步骤:
- 在需要渲染的子组件上使用v-bind,绑定要传递给父组件的data数据
- 在子组件中使用props接受父组件传来data数据
用props接受数据时,有两种写法:
// (1)数组写法
props:["msg"]
// (2)对象写法
props:{
msg:{
type:String,
}
}
//或
props:{
msg:String
}
接下来我们通过一个例子,说明父组件如何向子组件传递值
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<!-- 1.引入vue -->
<script src="lib/vue.js"></script>
</head>
<body>
<div id="box">
<!-- 3.将组件的内容引入-->
<!-- 4.在子组件中用v-bind绑定一个属性mytext(v-bind的缩写:mytext),
msg是父组件传给子组件的值 -->
<navbar :mytext='msg'></navbar>
<!-- 通过绑定传过来的数据是变量,否则就是一个字符串 -->
<navbar mytext='msg'></navbar>
</div>
<script>
// 2.用vue来定义全局组件,并且命名为nav
Vue.component("navbar",{
//template模板,写组件的内容
template:`
<div>
<span>我是导航栏---{{mytext}}</span>
</div>
`,
// 5.用props接受父组件传来的属性
// 通过{{mytext}}进行访问
props:['mytext']
// props:{
// mytext:String
// }
})
// vue实例 是一个根组件
new Vue({
el:"#box",
data:{
msg:"我是父组件传来的"
}
})
</script>
</body>
</html>
二. 子传父
基本步骤:
- 在需要渲染的子组件上使用v-on,监听父组件传给子组件的methods方法
- 在子组件中使用this.$emit()调用传递过来的方法,同时传递子组件的数据
接下来我们通过一个例子,说明子组件如何向父组件传递值
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<!-- 1. 引入vue -->
<script src="lib/vue.js"></script>
</head>
<body>
<div id="box">
<!-- 4.将组建内容传入 -->
<!--7. 在子组件上调用父组件方法,v-on:event的简写是@event event是事件名称-->
<child @event="handleEvent"></child>
</div>
<script>
// 3. 使用vue创建组件,并命名为child
Vue.component("child",{
template:`
<div>
child-<button @click="handleClick()">click</button>
</div>
`,
data(){
return {
text:"child定义的状态"
}
},
methods:{
//5. 子组件的点击事件
handleClick(){
//$emit 触发,分发
//6. 在子组件中通过this.$emit()触发 event是要触发的事件名,10000是参数
this.$emit("event",10000)
}
}
})
// 2. 创建vue实例
new Vue({
el:"#box",
methods:{
//8. 父组件中的方法
handleEvent(a){
console.log("已转",a)
}
}
})
</script>
</body>
</html>
三.兄弟之间传值
基本步骤:
- 实例化vue,并创建两个子组件,给其中一个子组件绑定点击事件,当点击时,改变另一个子组件的内容
- 创建一个空的vue实例,命名为bus,即中央事件总线.
用法:
(1) 用bus. o n 来 负 责 监 听 信 息 , 接 受 信 息 ( 2 ) 用 b u s . on来负责监听信息,接受信息 (2) 用bus. on来负责监听信息,接受信息(2)用bus.emit来触发,发送信息
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>Examples</title>
<meta name="description" content="">
<meta name="keywords" content="">
<link href="" rel="stylesheet">
<script type="text/javascript" src="lib/vue.js"></script>
</head>
<body>
<div id="box">
<child1></child1>
<child2></child2>
</div>
<script type="text/javascript">
//中央事件总线
var bus=new Vue()
Vue.component("child1",{
template:`
<div>
child1-<button @click="handleClick()">click</button>
</div>
`,
methods: {
handleClick(){
// bus.$emit触发事件,并将信息发送给child2
bus.$emit("event","我是child1")
// console.log("child1","$emit触发bus事件")
}
},
})
Vue.component("child2",{
template:`
<div>
child2
</div>
`,
//mounted()是生命周期之一,会自动被调用,当child1上dom树时就会被执行,立即监听事件
mounted() {
// bus.$on 自动执行监听事件,接受来自child1的信息,监听的事件名与$emit触发的事件名必须相同
bus.$on("event",(data)=>{
console.log("child2函数被执行",data)
})
},
})
var vm = new Vue({
el:"#box",
})
</script>
</body>
</html>
四.ref组件通信(不建议使用)
- ref放在标签上,能拿到原生的dom节点
- ref 放在组件上,能拿到组件对象,可以进行通信
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<script src="lib/vue.js"></script>
<script src="lib/axios.js"></script>
</head>
<body>
<div id="box">
<!-- ref放在标签上,拿到的是原生dom节点 -->
<!-- 在input标签中,加一个ref属性,能够拿到input节点 -->
<input type="text" ref="mytext">
<button @click="handleClick()">click</button>
<!-- ref 放在组件上 拿到的是组件对象 -->
<child ref="mychild"></child>
</div>
<script>
Vue.component("child",{
template:`
<div>child----{{childText}}</div>
`,
data(){
return {
childText:'child定义的'
}
}
})
new Vue({
el: "#box",
methods:{
handleClick(){
console.log(this.$refs.mytext.value)
console.log(this.$refs.mychild.childText)
}
}
})
</script>
</body>
</html>
注意:由于refs拿到的是整个dom节点或是组件对象,当父组件通过refs改变其子组件的值时,是不会通知子组件的,这样会导致子组件的值的状态会变得及其不确定,会使代码特别’'自由".refs的方式暴露了vue不是严格MVVM,绕过了vue,不要状态去做转呈,一旦使用过火,会使得数据,视图跟状态完全不匹配,会使状态不再受控制,耦合度太高,易出现问题.