vue组件传值(高级)、属性传值、反向传值、跨级传值实例详解

目录
  • 一、属性传值——父传子
  • 二、反向传值——子传父$emit
  • 三、反向传值——子传父--sync
  • 四、反向传值——子传父--v-model
  • v-model指令的修饰符:
  • 五、多层(跨级)组件传值
  • 六、$ parent/$root、$children/$refs
  • 七、Vue 依赖注入 - Provide/Inject(重点)
  • 八、中央事件总线bus

一、属性传值——父传子

父组件通过属性传值给子组件 父组件修改数据后会刷新页面并重新传值给子组件

子组件可以修改父组件传的值并刷新自己的页面 但是并不会修改父组件中的值

父组件App:

<template>
  <div id="app">
    <Box v-for="(item, index) in arr"
    :key="item.id"
    :employee="item.employee"
    :salary="item.salary"></Box>
    <p>总工资:{{total}}</p>
  </div>

</template>

<script>
import Box from "./Box.vue";
export default {
  data() {
    return {
      arr: [
        { id: 1, employee: "haha", salary: 3221 },
        { id: 2, employee: "xixi", salary: 4262 },
        { id: 3, employee: "yoyo", salary: 3122 }
      ]
    };
  },
  components: {
    Box
  },
  computed:{
    total(){
      let sum=0
      for (let i = 0; i < this.arr.length; i++) {
        sum+=this.arr[i].salary
      }
      return sum
    }
  }
};
</script>

子组件Box:

<template>
	<div>
		<span>员工:{{employee}}  工资:{{salary}}</span>
		<button @click="change">涨工资</button>
	</div>
</template>

<script>
	export default {
		props:["employee","salary"],
		methods:{
			change(){
				this.salary+=500
			}
		}
	}
</script>

 结果显示:

二、反向传值——子传父$emit

在父组件中绑定事件 事件被触发后获取子组件传的值 修改data中的数据 刷新页面

在子组件修改数据后 触发子组件中的父组件的事件 并传新值$emit("事件","值")

父组件App:

<template>
  <div id="app">
    <Box @mychange="fn" v-for="(item, i) in arr"
    :key="item.id"
    :employee="item.employee"
    :salary="item.salary"
    :index="i"></Box>
    <p>总工资:{{total}}</p>
  </div>

</template>

<script>
import Box from "./Box.vue";
export default {
  data() {
    return {
      arr: [
        { id: 1, employee: "haha", salary: 3221 },
        { id: 2, employee: "xixi", salary: 4262 },
        { id: 3, employee: "yoyo", salary: 3122 }
      ]
    };
  },
  components: {
    Box
  },
  methods:{
    fn(newsalary,index){
     //父组件接收到子组件传来的新值更新自己的数据 并重新传值 刷新页面
      this.arr[index].salary=newsalary
			this.$set(this.arr,index,this.arr[index])
    }
  },
  computed:{
    total(){
      let sum=0
      for (let i = 0; i < this.arr.length; i++) {
        sum+=this.arr[i].salary
      }
      return sum
    }
  }
};
</script>

子组件Box:

<template>
	<div>
		<span>员工:{{employee}}  工资:{{salary}}</span>
		<button @click="change">涨工资</button>
	</div>
</template>

<script>
	export default {
		props:["employee","salary","index"],
		methods:{
			change(){
				let newsalary=this.salary+500
                 //触发父组件的事件 同时将修改后的数据传给父组件
				this.$emit("mychange",newsalary,this.index)
			}
		}
	}
</script>

结果显示: 

三、反向传值——子传父--sync

子:this.$emit("updata:a","更改的值")

父:<Box :a.sync="msg"></Box>

.sync 帮忙修改了父组件的数据 不用父组件再绑定事件获取新值修改自己的数据

父组件App:

<template>
	<div>
		<h1>app组件--{{msg}}</h1>
		<Box :a1.sync="msg"></Box>
	</div>
</template>
<script>
	import Box from "./Box.vue"
	export default {
		data() {
			return {
				msg: "app的数据",
			}
		},
		components: {
			Box
		},
	}
</script>

子组件Box:

<template>
	<div>
		<h2>box组件--a1--{{a1}}</h2>
		<button @click="change">修改a1中的数据</button>
	</div>
</template>

<script>
	export default {
		props:["a1"],
		methods:{
			change(){
				console.log("点击了按钮")
				// 由以下两步操作,变为了一步:
				 //this.a1="box修改了a1的值"
				// this.$emit("myevent","box修改了a1的值")
				this.$emit("update:a1","box修改了a1的值")
			}
		}
	}
</script>

结果显示: 

四、反向传值——子传父--v-model

v=model <----语法糖---->  :value="msg"  @input="fn"

父:<Box :v-model="msg"></Box>

子:props:["value"]    this.$emit("input","修改的值")  触发input事件

父组件中:

<template>
	<div class="app">
		<h2>app组件--{{msg}}</h2>
		<Box v-model="msg"></Box>
	</div>
</template>
<script>
	import Box from "./Box.vue"
	export default {
		data() {
			return {
				msg:"app组件的数据"
			}
		},
		components: {
			Box
		},
		methods:{
		}
	}
</script>

子组件中:

<template>
	<div class="box">
	  <h2>box组件--{{value}}</h2>
	  <button @click="change">change</button>
	</div>
</template>

<script>
	export default {
		props:["value"],
		methods:{
			change(){
				this.$emit("input","box修改了数据")
			}
		}
	}
</script>

  结果显示: 

v-model指令的修饰符:

1、lazy修饰符--双向绑定时,当光标离开时才更新对应的变量

  • 用户使用v-model之后,用户每次修改输入内容,都会将后台的数据同时绑定。
  • 为了避免这种情况的发生,使用lazy修饰符来进行限定。
  • 只有当用户的input中失去焦点或用户点击回车后,才会将后台的数据进行修改更新。
  • 类似于懒加载和防抖的设计。
<input type="text" v-model.lazy="message">

2、number修饰符--自动将用户的输入值转为数值类型

  • 当用户在input中输入数字时,浏览器会默认将输入的数字转化为string类型。
  • 使用number修饰符来将输入的数字重新转为number类型。
<input type="text" v-model.number="age">

 3.trim修饰符--自动忽略输入内容的首尾空白字符 

  • 用户可能输入的字符串中含有空格,这样系统在处理时可能会出现错误。
  • 使用trim修饰符来去掉字符串首部或者尾部的所有空格。
 <input type="text" v-model.trim="userName">

五、多层(跨级)组件传值

父元素传的所有属性$attrs(属性传递) 

父元素传的所有监听器$listener(事件传递)

App:<Box1 :b1="msg" @x="xchange"></Box1>  事件虽然绑在子组件 但是是孙组件在触发事件

Box1:<Box2 v-bind="$attrs" v-on="$listener"></Box2> Box1只是作为中间人 将绑定的属性和事件都传给子组件Box2

Box2:props:["b1"] 触发上层传下来的App的事件 修改App组件的数据 再更新数据 重新刷新页面

App组件中:

<template>
	<div>
		 <h1>app-{{msg}}</h1>
		 <button @click="change1">点击修改app组件的msg</button>
		 <Box1 :b1="msg" @x="xchange"></Box1>
	</div>
</template>
<script>
	import Box1 from "./Box1.vue"
	export default {
		data() {
			return {
				msg: "app组件的数据"
			}
		},
		methods:{
			change1(){
				this.msg="app组件修改了msg的数据"
			},
			xchange(arg){
				this.msg=arg
			}
		},
		components:{
			Box1
		}
	}
</script>

Box1组件中:

<template>
	<div>
		<h1>{{$attrs.b1}}</h1>
		<Box2 v-bind="$attrs" v-on="$listeners"></Box2>
	</div>
</template>

<script>
	import Box2 from "./Box2.vue"
	export default {
		components:{
			Box2
		},
		methods:{
			look(){
				console.log(this.$attrs)
			}
		}
	}
</script>

Box2组件中:

<template>
	<div>
		<h3>box2--{{b1}}</h3>
		<button @click="change">change</button>
	</div>
</template>

<script>
	export default {
		props:["b1"],
		methods:{
			change(){
				this.$emit("x","box2修改了数据")
			}
		}
	}
</script>

结果显示:

六、$ parent/$root、$children/$refs

$root: 访问根组件vm对象,所有的子组件都可以将这个实例作为一个全局 store 来访问或使用,现在有更好的技术vuex代替。
 $parent:访问父组件对象,直接操作父组件的data数据,不需要再使用属性传值,但是容易出现渲染混乱之后只渲染一个的情况 可以连点 this.parent.parent... 
 $children:访问子组件对象数组,不是子元素 不能保证顺序,没有按照顺序加载,加载顺序是混乱的也不是响应式的
 $refs:只会在组件渲染完成之后生效,并且它们不是响应式的。应该避免在模板或计算属性中访问 $refs。在组件或者原生元素绑定ref属性(类似于id)  在父组件中可以通过 this.$refs访问到它

App组件:

<template>
	<div>
		<h1>app组件--{{msg}}</h1>
		<div>
			<Box1></Box1>
           <!--虽然Box1组件写在div里面 但是.$parent指的还是父组件App 而非div-->
		</div>
	</div>
</template>
<script>
	import Box1 from "./Box1.vue"
	export default {
		data() {
			return {
				msg:"app组件的数据"
			}
		},
		methods: {},
		components: {
			Box1
		}
	}
</script>

Box1组件:

<template>
	<div>
		<button @click="look">box1</button>
		<Box2></Box2>
		<Box2></Box2>
		<p ref="p1">ref</p>
		<button @click="getref">获取ref</button>
	</div>
</template>

<script>
	import Box2 from "./Box2.vue"
	export default {
		components: {
			Box2
		},
		methods: {
			getref(){
				console.log(this.$refs)
			},
			look() {
				console.log(this,this.$parent,this.$children,this.$root)
				this.$parent.msg="box1修改了app的数据"
			}
		}
	}
</script>

Box2组件:

<template>
	<div>
		<p>{{$parent.$parent.msg}}</p>
		<button @click="change1">box2-change</button>
	</div>
</template>

<script>
	export default {
		methods:{
			change1(){
				this.$parent.$parent.msg="box2修改了数据"
			}
		}
	}
</script>

结果显示:

七、Vue 依赖注入 - Provide/Inject(重点)

注:Provide和Inject绑定并不是可响应的

父组件使用:provide:提供数据

把data中的数据提供给子孙组件

// provide选项提供变量
    provide: {
      message: 'provided by father'
    },

inject:["message"]

八、中央事件总线bus

自定义事件的语法:

Vue提供的技术:某继承Vue的组件有三个功能:

1.触发x组件的a事件:x.$emit("a事件",参数)

2.给x组件绑定a事件:x.$on("a事件",监听器函数)

3.给x组件解绑a事件:x.$off("a事件",监听器函数)

通过创建一个新的vm对象,专门统一注册事件,供所有组件共同操作,达到所有组件随意隔代传值的效果:

main.js:

Vue.prototype.$bus = new Vue({
  methods: {
    //绑定事件
    on(eventname, callback) {
      this.$on(eventname, callback)
    },
    //触发事件
    emit(eventname, ...arg) {
      this.$emit(eventname, ...arg)
    },
    //解绑事件
    off(eventname, callback) {
      this.$off(eventname, callback)
    },
  }
})

使用:

this.$bus.on("事件",监听器函数)

this.$bus.emit("事件","参数")

this.$bus.off("事件",监听器函数)

示例:

组件1:
 this.$bus.on('changedFormObject',(val) =>{
            //接受并处理传过来的值:val
            this.msg = val;
        });

组件2:
this.$bus.emit('changedFormObject',this.inputValue);//把组件2的data中的给inputValue值传给组件1

到此这篇关于vue组件传值(高级)、属性传值、反向传值、跨级传值的文章就介绍到这了,更多相关vue组件传值内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Vue.js 前端路由和异步组件介绍

    目录 文章目标 P6 P6+ ~ P7 一.背景 二.前端路由特性 三.面试!!! 四.Hash 原理及实现 1.特性 2.如何更改 hash 3.手动实现一个基于 hash 的路由 五.History 原理及实现 1.HTML5 History 常用的 API 2.pushState/replaceState 的参数 3.History 的特性 4.面试!!! 5.手动实现一个基于 History 的路由 六.Vue-Router 1.router 使用 2.动态路由匹配 3.响应路由参数的变

  • 关于找到任意组件实例的方法

    目录 找到任意组件实例的方法 vue常用组件库 移动端常用组件库 pc端常用组件库 找到任意组件实例的方法 由一个组件,向上找到最近的指定组件 /**  * 由一个组件,向上找到最近的指定组件  * @param {*} context 当前上下文,比如你要基于哪个组件来向上寻找,一般都是基于当前的组件,也就是传入 this  * @param {*} componentName 要找的组件的 name  */ function findComponentUpward(context, comp

  • Vue中子组件的显示与隐藏方式

    目录 子组件的显示与隐藏 第一步 使用v-show 1.1 父组件 1.2 子组件 2 第二步 父子组件传参 2.1 父组件 2.2 子组件 子组件的显示与隐藏 在使用Vue开发前端页面的过程中,经常都会遇到需要在父组件中控制子组件的显示/隐藏,比如弹出窗口.最简单的方法就是:通过父子组件间的数据双向绑定来实现.这种方法虽然简单,但只是针对于父与子组件这种关系来实现的.如果是子组件与子组件之间,可以考虑使用Vuex来完成. 另外我自己也是一个前端小白,为了更方便大家理解,我将代码拆分成了两个步骤

  • Vue浅析讲解动态组件与缓存组件及异步组件的使用

    目录 1.什么是动态组件 2.如何实现动态组件渲染 3.如何实现缓存组件 4.异步组件 1.什么是动态组件 当我们希望页面中的某个地方,在不同组件之间进行动态切换,这时候除了条件渲染,还可以使用动态组件. 2.如何实现动态组件渲染 vue提供了一个内置的组件,专门用来实现动态组件的渲染:通过 is 属性动态指定要渲染的组件 因为要渲染的组件是不确定的,所以要通过data申明一个变量用来接收组件的名称,用 :is 动态绑定这个变量到组件中,通过按钮添加事件改变变量的值来切换相应组件 案例: //父

  • vue任意关系组件通信与跨组件监听状态vue-communication

    众所周知,组件式开发方式给我们带来了方便,不过也引入了新的问题,组件之间的数据就像被一道无形的墙隔开,如果我们希望临时让两个组件直接通信,vuex 太巨,而 $emit 又不好维护 provider 不可控 这个时候就该今天的主角 vue-communication 登场了! vue-communication介绍 他是一个可观测可调试的vue组件通信方案 任意关系组件可直接通信 支持跨组件监听数据变化 支持发送离线数据 安装 yarn add vue-communication // 或者 n

  • vue中手动封装iconfont组件解析(三种引用方式的封装和使用)

    目录 准备 封装 unicode引用封装 font-class引用封装 symbol引用封装 引入 全局引入 局部引入 使用 在线使用 有时候会因网络问题影响用户体验:直接放在 本地使用 ,如果过多使用也会显得繁琐,所以就可以将其封装成一个组件,也方便维护.​ 封装基于阿里巴巴图标库的项目图标. 准备 将项目内的图标下载至本地 在了路径 src/assets 下新建文件夹 iconfont ,用来存放字体图标的本地文件 解压下载到本地的字体图标文件,放到 iconfont 文件夹下 如过项目中没

  • Vue Ajax跨域请求实例详解

    一.设置config/index.js || proxyTable添加 proxyTable: { '/api': { target: 'http://192.168.48.239:8080/ydzl', changeOrigin: true, pathRewrite: { '^/api': '' } } 二.mian.js 添加vue全局属性 Vue.prototype.HOST = '/api' 三.如果是post的话 1.修改数据格式 transformRequest: [function

  • Vue import from省略后缀/加载文件夹的方法/实例详解

    目录 简介 省略后缀 说明 官网网址 详解 文件名相同的处理流程 加载文件夹 简介 说明 详解 实例 1. 路由配置中导入layout文件夹 2.layout/index.vue引入目录 3.components/index.js引入各个组件 简介 本文介绍Vue在import时省略后缀以及import文件夹的方法. 省略后缀 说明 可以配置省略后缀,比如:test.js,只用test即可. 官网网址 解析(Resolve) | webpack 中文文档 详解 配置文件:webpack.base

  • vue组件传值(高级)、属性传值、反向传值、跨级传值实例详解

    目录 一.属性传值——父传子 二.反向传值——子传父$emit 三.反向传值——子传父--sync 四.反向传值——子传父--v-model v-model指令的修饰符: 五.多层(跨级)组件传值 六.$ parent/$root.$children/$refs 七.Vue 依赖注入 - Provide/Inject(重点) 八.中央事件总线bus 一.属性传值——父传子 父组件通过属性传值给子组件 父组件修改数据后会刷新页面并重新传值给子组件 子组件可以修改父组件传的值并刷新自己的页面 但是并

  • JSP Spring配置文件中传值的实例详解

    JSP Spring配置文件中传值的实例详解 通过spring提供方法,在配置文件中取传值 调用get方法  targetObject :指定调用的对象       propertyPath:指定调用那个getter方法 例1: public class Test1 { private String name = "nihao"; public String getName() { return name; } } Xml代码 <bean id="t1" cl

  • 微信小程序中子页面向父页面传值实例详解

    微信小程序中子页面向父页面传值实例详解 上面一张图是编辑款项页面,下面一张图是点击了编辑款项页面中选择好友的图标后打开的子页面.这个时候点选子页面的某个好友时,需要把好友的名字传递回编辑款项父页面. 采取的方法: 从页面路由栈中直接获取和操作目标Page对象,这种方式,是通过调用小程序的API: getCurrentPages(),来获取当前页面路由栈的信息,这个路由栈中按照页面的路由顺序存放着相应的Page对象,我们可以很容易的获取到上一级页面的完整Page对象,从而使直接调用Page对象的属

  • ASP.NET页面之间传值的方式之Application实例详解

    Application Application变量在整个应用程序生命周期中都是有效的,类似于使用全局变量一样,所以可以在不同页面中对它进行存取.它和Session变量的区别在于,前者是所有的用户共用的全局变量,后者是各个用户独有的全局变量. 举例来解释: 网站访问的计数器变量一般采用Application变量,多个请求访问时共享这一个变量,均可对它进行操作,该变量可以被整个应用程序的各个页面直接使用. 用户登陆的帐号名一般采用Session变量,多个请求访问时有各自的Session变量,只能对自

  • vue 组件高级用法实例详解

    一.递归组件 组件在它的模板内可以递归地调用自己, 只要给组件设置name 的选项就可以了. 示例如下: <div id="app19"> <my-component19 :count="1"></my-component19> </div> Vue.component('my-component19',{ name: 'my-component19', //其实当你利用 Vue.component 全局注册了一个组件

  • Vue组件中prop属性使用说明实例代码详解

    Prop 的大小写 (camelCase vs kebab-case) HTML 中的特性名是大小写不敏感的,所以浏览器会把所有大写字符解释为小写字符.这意味着当你使用 DOM 中的模板时,camelCase (驼峰命名法) 的 prop 名需要使用其等价的 kebab-case (短横线分隔命名) 命名: Vue.component('blog-post', { // 在 JavaScript 中是 camelCase 的 props: ['postTitle'], template: '<h

  • vue组件中的样式属性scoped实例详解

    Scoped CSS Scoped CSS规范是Web组件产生不污染其他组件,也不被其他组件污染的CSS规范. vue组件中的style标签标有scoped属性时表明style里的css样式只适用于当前组件元素 它是通过使用PostCSS来改变以下内容实现的: <style scoped> .example { color: red; } </style> <template> <div class="example">hi</di

  • vue组件讲解(is属性的用法)模板标签替换操作

    vue中is的属性引入是为了解决dom结构中对放入html的元素有限制的问题,譬如ul里面要接上li的标签,引入is的属性后,你完全可以写成这样 <div class="language-html"> <ul> <li is="row"></li> </ul> </div> 这样会保证dom结构在浏览器的正常渲染,尽量避免在不正确的结构中直接使用组件 <script> Vue.com

随机推荐