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父子组件数据双向绑定的资料请关注我们其它相关文章!

(0)

相关推荐

  • 浅析Vue3中通过v-model实现父子组件的双向数据绑定及利用computed简化父子组件双向绑定

    目录 一.vue2 中 sync 修饰符的功能在 vue3 中如何呈现? 1.sync 修饰符回顾 2.sync 的语法糖功能在vue3中如何编写使用? 二.如何通过v-model实现父子组件的双向数据绑定 1.单个数据双向绑定 2.多个数据双向绑定 - 与单数据绑定差别不大 3.利用 computed 简化父子组件双向数据绑定 一.vue2 中 sync 修饰符的功能在 vue3 中如何呈现? 1.sync 修饰符回顾 1.vue 规则:props 是单向向下绑定的,子组件不能修改 props

  • Vue父子组件传值的三种方法

    目录 前言 一.Vue父子传值的方法 二.方法详解 1.props / $emit 2.$parent / children 3.$ref 总结 提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 前言 例如:Vue的学习是路阻且艰的,这是一个系列文章,帮助vue的新手可以快速上路,创建的自己的项目,该系列文章主要讲解作者在vue学习之路上,创建项目中最重要的知识,因为笔者水平有限,希望大家多多指正,该系列文章旨在让大家感受vue的便捷,详细学习vue希望大家多多观看官方文档. 一

  • 关于Vue3父子组件emit参数传递问题(解决Vue2this.$emit无效问题)

    目录 1.解决this.$emit无效问题 2.Vuex问题 3.总结 之前写了一篇Vue3路由跳转问题的博客,发现还是有很多同学对基本的使用改变还没有了解,于是我就顺道把常用的组件间传递的方式也写一下吧....... 注意的是: 1.Vue3中不在强调this的使用,可以说你在setup中完全不能用this,不像Vue2中把全部的内容都集成到this中. 2.Vue3现在由于compositionAPI的方式可以说是弱化了Vuex的存在(当然Vuex现在可以用没什么变化). 3.如果您有Vue

  • Vue实现父子组件页面刷新的几种常用方法

    目录 1.原地页面重新加载(不推荐) 2.空白页面作为过渡 3.使用Provide / Inject组合控制显示 4.v-on:param父组件监听子组件事件 参考文档: 很多时候我们在操作过页面时候,特别是增删改操作之后,数据会有所改变,这个时候我们希望返回的界面中的数据要和数据库中的数据进行同步,就需要刷新当前页面,如果是使用ajax可以使用异步请求实现页面的局部刷新,Vue常用的几种刷新页面方法如下: 1.原地页面重新加载(不推荐) this.$router.go(0) //根据路由重新定

  • vue3 父子组件间相互传值方式

    目录 vue3父子组件相互传值 父向子传值 子组件向父组件传值 vue3父子组件传值的注意事项 解决办法:两种 vue3父子组件相互传值 父向子传值 父 <pie-chart :pieData="post_data.pid" /> 父组件只需在子组件上声明一个变量即可. :代表变量,可以传变量;否则只能传常量 子 export default {     props:['pieData'],     setup(props,ctx) {         const pie_

  • vue3自定义组件之v-model实现父子组件双向绑定

    vue3 v-model父子组件双向绑定 vue3.x移除了vue2.x的model选项,自定义组件双向绑定不在使用以下方法: // vue2的v-model双向绑定方法 model: {      prop: 'value', //3.x默认值改为了modelValue      event: 'input' //3.x默认值改为了update:modelValue    }, //使用 this.$emit('input', index); vue3.x采用以下方式(v-model默认对应的

  • Vue中一个组件调用其他组件的方法详解(非父子组件)

    目录 前言 方式一:引用式 方式二:vuex 1.src/store/index.js 2.被使用组件- A 页面(组件) 3.使用触发页面-B 页面(组件) 方式三:使用事件总线eventBus定义全局事件 1.src/main.js 2.触发页面-B组件/发布事件 3.接收页面-A组件/订阅事件 4.移除事件 总结 前言 Vue中,一个组件调用其他组件的方法(非父子组件) 场景——B页面(组件)想调用 A页面(组件)中的方法:但是两个页面(组件)毫无关联(刷新 A的数据). 方式一:引用式

  • Vue3父子组件互调方法的实现

    目录 一.父组件调用子组件方法 1.子组件 2.父组件 3.测试结果 4.关于 defineExpose 的官方文档 二.子组件调用父组件方法 1.子组件 2.父组件 3.测试结果 4.关于 defineEmits 的官方文档 下面演示均为使用 setup 语法糖的情况! 一.父组件调用子组件方法 下面演示为使用 setup 语法糖的情况,值得注意的是子组件需要使用 defineExpose 对外暴露方法,父组件才可以调用! 1.子组件 <template> </template>

  • vue父子组件动态传值的几种方式及注意问题详解

    1.vue父组件向子组件动态传值的两种方法 在一些项目需求中需要父组件向子组件动态传值,比如我这里的需求是,父组件动态通过axios获取返回的图片url数组然后传给子组件,上传图片的子组件拿到该数组后进行遍历并展示图片,因为有时候获取到的会是空,所以这里要考虑到动态获取. 方法有两种, vue父组件向子组件动态传值方法一: props传值,这里注意一个问题,传过来的值需要用watch监听并赋值,否则这里获取到的是空数组 父组件: <uploadImg :width="200" :

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

    既然有父传子那么肯定有子传父,有子传父肯定也有两者之间相互绑定 这里我们先看一下子传父的写法: 一.子传父:$emit() 看代码: <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>子传父</title> <script src="https://cdn.jsdelivr.net/npm/vue"></sc

  • 前端框架Vue父子组件数据双向绑定的实现

    目录 一.父子组件单向传值 1.父向子传值 2.子向父传值 二.父子组件数据双向绑定 实现思路: 父 向 子 组件传值:使用 props 属性.( props 是property[属性] 的复数简写 ) 子 向 父 组件传值:使用自定义事件. 一.父子组件单向传值 1.父向子传值 父向子组件传值,子组件接收到数据之后,保存到自己的变量中. //父组件写法 <cld :numP="num" ></cld> //子组件定义以及数据 components:{ cld:

  • Vue使用.sync 实现父子组件的双向绑定数据问题

    1.前言 最近在vue 项目中有一个需求, 就是我需要根据不同的类型在页面中放不同的组件, 组件需要跟当前页面的数据进行双向绑定,如果都写在同一个页面 代码会显得比较多,毕竟我当前页面已经7-800行代码了 所以我需要把一些元素定义成组件 ,封装起来,所以就会遇到 数据的传值绑定问题 2.父组件 首先我们来看看官方文档 [ https://cn.vuejs.org/v2/guide/components.html#sync-修饰符 ] .sync 修饰符所提供的功能.当一个子组件改变了一个 pr

  • vue 自定义组件 v-model双向绑定、 父子组件同步通信的多种写法

    上篇文章给大家介绍了浅析Vue自定义组件的v-model,大家可以参考下.接下来通过本文给大家介绍vue 自定义组件 v-model双向绑定. 父子组件同步通信的多种写法,具体详情如下所示: 父子组件通信,都是单项的,很多时候需要双向通信.方法如下: 1.父组件使用:msg.sync="aa"  子组件使用$emit('update:msg', 'msg改变后的值xxx') 2.父组件传值直接传对象,子组件收到对象后可随意改变对象的属性,但不能改变对象本身. 3.父组件使用: v-mo

  • vue3父子组件传值 双向绑定及注意问题小结

    attribute agruments vue3父子组件传值 双向绑定 及注意事项 https://www.jb51.net/article/269785.htm 可以参考下 首先注意 父子组件传值是单项数据流,vue3中子组件是不能直接修改父组件数据的,vue2中是可以直接使用sync的语法,直接进行修改的而sync修饰符的作用则是简化事件声明及监听的写法. 注意事项: // 父组件 // v-model 没有指定参数名时,子组件默认参数名是modelValue <ChildComp v-mo

  • Vue 父子组件数据传递的四种方式( inheritAttrs + $attrs + $listeners)

    当我们在书写 vue 组件的时候,也许可能会用到数据传递:将父组件的数据传递给子组件,有时候也需要通过子组件去事件去触发父组件的事件: 每当我们遇到这样的需求的时候,我们总是会想到有三种解决办法: 通过 props 的方式向子组件传递(父子组件) vuex 进行状态管理(父子组件和非父子组件) vuex 非父子组件的通信传递 Vue Event Bus ,使用Vue的实例,实现事件的监听和发布,实现组件之间的传递. 后来再逛社区的时候我又发现了还有第四种传递方式, inheritAttrs +

  • 全面解析vue中的数据双向绑定

    1.vue中数据的双向绑定采用的时候,数据劫持的模式.其实主要是用了Es5中的Object.defineProperty;来劫持每个属性的getter,和setter.这也正是Vue不兼容IE8以下的原因. 2.Object.defineProerty(); var obj = {}; Object.defineProperty(obj,"hello",{ enumerable: true, //表示这个属性能够通过 for -- in 循环 (是否可枚举); configurable

  • vue实现简单数据双向绑定

    本文实例为大家分享了vue实现简单数据双向绑定的具体代码,供大家参考,具体内容如下 这里是简单的实现,有助于新手理解消化,当然vue要实现双向数据代理不可缺少,期待后续在更新 vue双向数据绑定 -> Object.defineProperty() //2.0核心语法 -> 数据代理 -> 双向绑定 -> 订阅发布模式 compile-> 模版解析 (template模版 html 指令 {{表达式}}) observer-> 观察者(订阅发布) data里的所有的属性

  • 详解基于Vue的支持数据双向绑定的select组件

    今天用Vue做一个小项目时需要用到多个select筛选功能,但是原生的太丑,如果直接写在当前页多个select处理起来又太繁琐,第三方ui又太大,所以就自己写了一个,并上传了GitHub仓库,仓库地址:https://github.com/tuohuang/vue-select 使用方法: 引入组件: import VueSelect from '../components/VueSelect' 注册组件 export default { components: { VueSelect } }

  • vue自定义组件实现双向绑定

    场景: 我们比较常用的父子组件之间的交互方式: 父组件通过props将数据流入到子组件: 子组件通过$emit将更新后的数组发送的父组件: 今天,我们通过另一种方式实现交互,参考input框的v-model,实现自定义组件的双向数据绑定. 即:父组件值改变,子组件的值跟着改变:反之,子组件值发生变化,父组件值随之变化 子组件定义: 由于不能直接修改props属性值,我们这里定义valueData,通过监听实时接收value值,通过click方法修改valueData. 这里注意model语法糖p

随机推荐