Vue父子组件数据双向绑定(父传子、子传父)及ref、$refs、is、:is的使用与区别

 更新时间:2022年12月24日 14:38:11   作者:Nanchen_42  
这篇文章主要介绍了Vue父子组件数据双向绑定(父传子、子传父)及ref、$refs、is、:is的使用与区别,需要的朋友可以参考下

既然有父传子那么肯定有子传父,有子传父肯定也有两者之间相互绑定

这里我们先看一下子传父的写法:

一、子传父:$emit()

看代码:

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title>子传父</title>
		<script src="https://cdn.jsdelivr.net/npm/vue"></script>
	</head>
	<style type="text/css">
		button {
			margin-left: 5px;
		}
	</style>
	<body>
		<div id="app">
			<cpn1 @itemclick="cpnclick"></cpn1>
		</div>
		<template id="cpn1">
			<div>
				<button type="button" v-for="item in menu" :key="item.id"
					@click="btnclick(item)">{{item.name}}</button>
			</div>
		</template>
		<script type="text/javascript">
			const cpn = {
				template: "#cpn1",
				data() {
					return {
						menu: [{
								id: 'one',
								name: '首页'
							},
							{
								id: 'two',
								name: '分类'
							},
							{
								id: 'three',
								name: '购物'
							},
							{
								id: 'four',
								name: '我的'
							},
						],
					}
				},
				methods: {
					btnclick(item) {
						this.$emit('itemclick', item)
// 子传父 在子组件中做一个点击事件通过$emit派发出 给父组件 同时可以携带参数
					}
				}
			};
			const vm = new Vue({
				el: '#app',
				methods: {
					cpnclick(item) {
						console.log('cpnclick' + item.name);
					}
				},
				components: {
					"cpn1": cpn
				}
			})
			
		</script>
	</body>
</html>

打印效果:

两者之间的关系: 

 1、父组件可以使用 props 把数据传给子组件。
2、子组件可以使用 $emit 触发父组件的自定义事件。

二、监听原生点击事件:.native 

不加.native时,不会触发原生的点击事件

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title>不加native修饰符</title>
	</head>
	<style>
		div{
			cursor: pointer;
		}
	</style>
	<body>
		<div id="app">
          <cpn @click="handelClick"></cpn>    //    这里没有加native修饰符
		</div>
		<!-- 子组件 -->
		  <template id="cpn">
		    <div>
		      我是子组件
		    </div>
		  </template>
		<script src="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js"></script>
		<script>
			const cpn = {
				template:'#cpn',
			}
			const app = new Vue({
				el: "#app",
				methods: {
                  handelClick(){
					  console.log('click');
				  }
				},
				components:{
					cpn
				}
			})
		</script>
	</body>
</html>

效果如下: 

不加修饰符是不会监听到原生点击事件的。

如果是加了.native修饰符时:

 添加方法:

<cpn @click.native="handelClick"></cpn>

效果如下图所示:

三、组件通信的案例:

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
 
	</head>
	<body>
		<div id="app">
          <cpn :number1="num1" :number2="num2"></cpn>
		</div>
		<template id="cpn">
			<div>
				<h2>{{datanum1}}</h2>
				<input type="text" v-model="datanum1"/>
				<h2>{{datanum2}}</h2>
				<input type="text" v-model="datanum2"/>
			</div>
		</template>  
		<script src="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js"></script>
		<script>
			const cpn = {
				template:'#cpn',
				data(){
					return {
						datanum1:this.number1,
						datanum2:this.number2,
					}
				},
				props:{
					number1:{
						type:[String,Number]
					},
					number2:{
						type:[String,Number]
					},
				}
			}
			const app = new Vue({
				el: "#app",
				data() {
					return {
						num1:1,
						num2:2
					}
				},
				components:{
					cpn
				}
			})
		</script>
	</body>
</html>

效果如下:

 四、实现父子之间的值的双向绑定

在子组件中添加监听器,利用props和$emit来进行父子之间的双向绑定

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<body>
		<div id="app">
			<cpn :number1="num1" :number2="num2" @dataclick1="changeClick1" @dataclick2="changeClick2"></cpn>
		</div>
		<template id="cpn">
			<div>
				<h2>{{datanum1}}</h2>
				<h3>number1:{{number1}}</h3>
				<input type="text" v-model="datanum1" />
				<h2>{{datanum2}}</h2>
				<h3>number2:{{number2}}</h3>
				<input type="text" v-model="datanum2" />
			</div>
		</template>
		<script src="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js"></script>
		<script>
			const cpn = {
				template: '#cpn',
				data() {
					return {
						datanum1: this.number1,
						datanum2: this.number2
					}
				},
				props: {
					number1: {
						type: [String, Number]
					},
					number2: {
						type: [String, Number]
					}
				},
				watch: {
					datanum1(n) {
						console.log('datanum1被监听了');
						this.$emit('dataclick1', n / 100)
					},
					datanum2(n) {
						console.log('datanum2被监听了');
						this.$emit('dataclick2', n * 100)
					}
				}
			}
			const app = new Vue({
				el: "#app",
				data() {
					return {
						num1: 1,
						num2: 2
					}
				},
				methods: {
					changeClick1(value) {
						this.num1 = value
					},
					changeClick2(value) {
						this.num2 = value
					}
				},
				computed: {
 
				},
				components:{
					cpn
				}
			})
		</script>
	</body>
</html>

效果 

 一个是除10一个是

五、父访问子 $refs

JavaScript中获取元素可以使用document.querySelector,那可以在Vue中使用吗?

我们可以测试一下

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<script src="https://cdn.jsdelivr.net/npm/vue"></script>
	</head>
	<body>
		<div id="app">
			<p id="bb" @click="handelClick" ref="aa">Nanchen</p>
		</div>
		<script type="text/javascript">
			const vm = new Vue({
				el: '#app',
				data() {
					return {
					}
				},
				methods: {
					handelClick(){
						var bb = document.querySelector('bb');
						console.log(bb);
					}		
				}
			})
		</script>
	</body>
</html>

打印结果:

 答案是可以的,但是如果使用原生JS获取元素的话,那么用Vue就没有意义了,Vue中有特定的语法

官网解释:

$refs方式:ref 被用来给元素或子组件注册引用信息。引用信息将会注册在父组件的 $refs 对象上。如果在普通的 DOM 元素上使用,引用指向的就是 DOM 元素;如果用在子组件上,引用就指向组件实例

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<script src="https://cdn.jsdelivr.net/npm/vue"></script>
	</head>
	<body>
		<div id="app">
			<p id="bb" @click="handelClick" ref="aa">Nanchen</p>
		</div>
		<script type="text/javascript">
			const vm = new Vue({
				el: '#app',
				data() {
					return {
					}
				},
				methods: {
					/* handelClick(){
						var bb = document.querySelector('bb');
						console.log(bb);
					} */
					handelClick() {
						console.log(this.$refs.aa);
					}
				}
			})
		</script>
	</body>
</html>

效果与上图一致: 

六、使用$refs获取组件中的值

 既然可以获取普通元素那么也可以获得组件中的元素或者值

看这个例子:

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
 
	</head>
	<body>
		<div id="app">
          <cpn ref="aaa"></cpn>
		  <button @click="handelClick">点击</button>
		</div>
		<!-- 子组件 -->
		  <template id="cpn">
		    <div>
		      我是子组件
		    </div>
		  </template>
		<script src="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js"></script>
		<script>
			const cpn = {
				template:'#cpn',
				data(){
					return {
						name:'我是子组件的name'    //获取子组件的属性
					}
				},
				
			}
			const app = new Vue({
				el: "#app",
				methods: {
                  handelClick(){
					  console.log(this.$refs.aaa.name);
				  }
				},
				components:{
					cpn
				}
			})
		</script>
	</body>
</html>

效果如下: 

下面看一个扩展:

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<script src="https://cdn.jsdelivr.net/npm/vue"></script>
	</head>
	<body>
		<div id="app">
			<count ref="one" @change="handclick"></count>
			<count ref="two" @change="handclick"></count>
			<h2>{{total}}</h2>
		</div>
		
		<script type="text/javascript">
		Vue.component('count',{
			template:
			`<div @click="handclick">
				{{number}}
			</div>`,
			data(){
				return{
					number:0
				}
			},
			methods:{
				handclick(){
					this.number++;
					this.$emit('change')
				}
			}
		})
			const vm = new Vue({
				el:'#app',
				data(){
					return{
						total:0
					}
				},
				methods:{
					handclick(){
						this.total= this.$refs.one.number + this.$refs.two.number
					}
				}
			})
		</script>
	</body>
</html>

效果如下:

 

 不仅如此,ref还可以调用组件中的方法:

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<body>
		<div id="app">
          <hello-world ref="hello"></hello-world>
		   <button @click="getHello">获取helloworld组件中的值</button>
		</div>
		<script src="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js"></script>
		<script>
			Vue.component('helloWorld',{
				template:`<div>helloWorld</div>`,
				data(){
					return {
						number:0
					}
				},
				methods:{
					/*handelClick(){
						console.log('我是子组件的方法');
					}*/
				}
			})
			const app = new Vue({
				el: "#app",
				data: {
					
				},
				methods: {
                 getHello(){
					/* this.$refs.hello.handelClick(); */
					console.log(this.$refs.hello.$el.innerHTML);
				 }
				},
			})
		</script>
	</body>
</html>

效果如下:

 六、is与:is

is

作用:解决了html模板的限制。

看下面这段代码:

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<script src="https://cdn.jsdelivr.net/npm/vue"></script>
	</head>
	<body>
		<div id="app">
			<table>
				<row></row>
			</table>
		</div>
		
		<script type="text/javascript">
		Vue.component('row',{
			template: '<tr><td>111</td></tr>'
		})
			const vm = new Vue({
				el:'#app',
				data(){
					return{
						
					}
				},
			})
		</script>
	</body>
</html>

会正常输出

 但是:

会发现tr并不在table中,

解决办法:

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
 
	</head>
	<body>
		<div id="app">
          <table>
				<tr is="row"></tr>
			</table> 
		</div>
		<script src="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js"></script>
		<script>
			Vue.component('row', {
				template: '<tr><td>111</td></tr>'
			})
			const app = new Vue({
				el: "#app",
			})
		</script>
	</body>
</html>

 打印结果:

用:is还可以用来绑定动态组件

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<script src="https://cdn.jsdelivr.net/npm/vue"></script>
	</head>
	<body>
		<div id="app">
			<component :is="type"></component>
			<button type="button" @click="changeClick">切换</button>
		</div>
		<script type="text/javascript">
		// 这里要定义两个全局组件
			Vue.component('child-one',{
				template:'<div>child-one</div>'
			}),
			Vue.component('child-two',{
				template:'<div>child-two</div>'
			})
			const vm = new Vue({
				el:'#app',
				data(){
					return{
						type:'child-one'
					}
				},
				methods:{
					changeClick(){
						  this.type = this.type === 'child-one' ? 'child-two' :'child-one'
					}
				}
			})
		</script>
	</body>
</html>

效果如下:

以上就是Vue父子组件数据双向绑定(父传子、子传父)及ref、$refs、is、:is的使用与区别的详细内容,更多关于Vue父子组件数据双向绑定的资料请关注脚本之家其它相关文章!

相关文章

  • Vue自定义组件使用事件修饰符的踩坑记录

    Vue自定义组件使用事件修饰符的踩坑记录

    vue提倡的是在方法中只有对数据的处理,所以提供了事件修饰符用于DOM的事件处理,下面这篇文章主要给大家介绍了关于Vue自定义组件使用事件修饰符的相关资料,需要的朋友可以参考下
    2021-05-05
  • 详解Vue.js在页面加载时执行某个方法

    详解Vue.js在页面加载时执行某个方法

    这篇文章主要介绍了详解Vue.js在页面加载时执行某个方法的实现代码,本文给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下
    2018-11-11
  • vue2路由中router-view不显示的原因及踩坑记录

    vue2路由中router-view不显示的原因及踩坑记录

    这篇文章主要介绍了vue2路由中router-view不显示的原因及踩坑记录,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-04-04
  • vue与electron实现进程间的通信详情

    vue与electron实现进程间的通信详情

    这篇文章主要介绍了vue与electron实现进程间的通信详情,本文主要介绍electron渲染进程和主进程间的通信,以及在渲染进程和主进程中常用的配置项,需要的朋友可以参考一下
    2022-09-09
  • Vue使用electron生成桌面应用过程详解

    Vue使用electron生成桌面应用过程详解

    这篇文章主要介绍了Vue使用electron生成桌面应用过程,很想使用 electron 制作一个桌面应用,但是真的上手使用的时候才发现 electron 的坑实在是太多了,先将遇到的坑记录在这里,遇到一个记录一个
    2023-04-04
  • vue v-if未生效问题及解决

    vue v-if未生效问题及解决

    这篇文章主要介绍了vue v-if未生效问题及解决方案,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-03-03
  • 解决vue无法加载文件C:\Users\Administrator\AppData\Roaming\npm\vue.ps1因为在此系统上禁止运行脚本问题

    解决vue无法加载文件C:\Users\Administrator\AppData\Roaming\npm\vue.ps

    这篇文章主要介绍了解决vue无法加载文件C:\Users\Administrator\AppData\Roaming\npm\vue.ps1因为在此系统上禁止运行脚本问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-03-03
  • vue中怎么区分不同的环境

    vue中怎么区分不同的环境

    这篇文章主要介绍了vue中怎么区分不同的环境,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-04-04
  • vue使用微信扫一扫功能的实现代码

    vue使用微信扫一扫功能的实现代码

    这篇文章主要介绍了vue使用微信扫一扫功能的实现代码,需要的朋友可以参考下
    2020-04-04
  • vue中vite.config.js配置跨域以及环境配置方式

    vue中vite.config.js配置跨域以及环境配置方式

    这篇文章主要介绍了vue中vite.config.js配置跨域以及环境配置方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-04-04

最新评论