vue——组件传值(高级)、属性传值、反向传值、跨级传值

2023-10-26

一、属性传值——父传子

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

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

  父组件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:接收提供的数据 created之后可以通过this访问到接收到的数据

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

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

vue——组件传值(高级)、属性传值、反向传值、跨级传值 的相关文章

  • 如何删除除任何特定 id 之外的元素

    假设有一个父 id 其中包含许多元素 我想删除除一个元素之外的所有元素 ex parent id children not id n remove
  • Jquery 悬停卡

    我在用着http designwithpc com Plugins Hovercard http designwithpc com Plugins Hovercard 但我不知道如何在悬停卡上声明 var 每个工作描述都有自己的 ID 当悬
  • 显示具有多个父代的 D3 树

    我目前有this http bl ocks org mbostock 4339083图已实现 我希望在描述具有多个父节点的子节点时保持结构和可折叠性 有没有办法做到这一点 我研究了力图 但我也想保留一组层次结构 这意味着 1 级的父级可以有
  • 在 Internet Explorer 中使用什么来监视 jscript 内存使用情况

    我们正在调试 GWT 应用程序 在 Firefox 中运行正常 在 IE6 0 中开始运行正常 但一段时间后 它就会崩溃并开始爬行 经过一些测试后 我们怀疑存在一些内存问题 使用了太多内存 内存泄漏等 除了使用taskmanager和pro
  • Vue 3 Composition API 提供/注入在单文件组件中不起作用

    我正在使用 Composition API 在 VueJS 3 中创建一个库 我实现了提供 注入 如中所述docs https v3 vuejs org guide composition api provide inject html i
  • 使用 Node.js 构建网站的最佳实践

    这个问题的答案是社区努力 help privileges edit community wiki 编辑现有答案以改进这篇文章 目前不接受新的答案或互动 我想知道如何使用 Node js 从头开始 开发一个网站 我明白我怎么能possibly
  • 如何在网站上使用 svg 元素制作块的屏幕截图?

    我在网站上创建了一个构造函数 其本质是将所选元素及其颜色 svg中的元素 添加到访问者选择的背景和背景颜色 png中的背景 中 然后必须单击 保存 结果 按钮并仅执行工作区的屏幕截图 我写了这个脚本 但它需要屏幕截图 但只有背景 并忽略选定
  • JavaScript 验证和 PHP 验证?

    我正在使用 jquery 验证插件来验证空表单 我还应该在 PHP 中检查一下以确保 100 正确吗 或者用 javascript 验证就可以了 谢谢 您应该始终在服务器上进行验证 如果用户以某种方式不使用 Javascript 提交表单
  • 导航栏下拉菜单(折叠)在 Bootstrap 5 中不起作用

    我在尝试使用以下命令创建响应式菜单或下拉按钮时遇到问题Bootstrap 5一切似乎都正常 导航图标和下拉图标出现 但它不起作用 当我单击nav图标或dropdown按钮 无dropdown menu apears 我想特别提到的是 我还包
  • 为什么 setTimeout 在 Chrome 中触发两次,而在 IE 或 Firefox 中则不然?

    有人能告诉我为什么 javascript 函数 生成新号码 在 Chrome 中触发两次 但在 IE 或 Firefox 中则不会 使用 Chrome 20 0 1132 57 IE9 和 Firefox 13
  • 按下回车键时不刷新页面

    我遇到了一些问题 只要表单中有输入 回车键就会触发页面刷新 下面的代码 如果按下回车并且文本区域 input 中没有输入任何文本 则不会刷新页面 但是如果按下回车并且 input中有输入或者光标位于文本区域 我不确定是什么触发了它 因为 s
  • React Router v4 不渲染组件

    React Router v4 渲染组件存在问题 在应用程序初始加载时 它将呈现与 URL 相对应的正确组件 但是 任何后续的组件Link单击不会呈现所需的组件 图书馆 反应路由器 4 2 2 https reacttraining com
  • 如何使用 Javascript 设置查询字符串

    有没有办法使用 javascript 设置查询字符串的值 我的页面有一个过滤器列表 单击该列表时 它将更改右侧的页内结果窗格 我正在尝试更新 url 的查询字符串值 因此如果用户离开页面 然后单击 后退 按钮 他们将返回到最后一个过滤器选择
  • onclick 事件中未调用函数

    我想在每个 YouTube 链接的末尾添加一些 HTML 以在 litebox 中打开播放器 到目前为止 这是我的代码 document ready function var valid url new RegExp youtube com
  • 改变 JavaScript 中的顶部填充

    以下是我在 css 中设置顶部填充的方法 body font size font size px margin 0 padding 100px 0 20px 0 width 100 important 如何使用最简单的 javascript
  • 使用 Javascript 设置 cookie [重复]

    这个问题在这里已经有答案了 我正在尝试构建我的第一个移动应用程序 它需要连接到我的 mysql 数据库并使用 json 返回数据 这很好 目前我有一个登录系统 一旦确定用户名和密码存在 它就会返回一条成功消息 对于下一步 我想在我的页面上使
  • 如何使用 JavaScript 或 jQuery 克隆 HTML 元素的样式对象?

    我正在尝试克隆元素的样式对象 这应该允许我在更改后重置所述元素的样式 例如 el style left 50px curr style left 50px Modify the elements style The cloned style
  • Highcharts jQuery 渲染问题 - 所有浏览器

    我在尝试使用构建堆积柱形图时遇到了一个奇怪的问题高图表 http www highcharts com 当图表呈现时 在您调整浏览器大小之前 不会显示列无论如何 导致图表重绘 我认为 图表的其余部分显示 轴 标题等 但不显示列本身 我在 I
  • 有没有办法使用 ko.observableArray 作为地图?

    有没有办法使用ko observableArray http knockoutjs com documentation observableArrays html像地图 字典一样 例如 var arr ko observableArray
  • Flot 库将 y 轴设置为最小值 0 和最大值 24

    如何将 y 轴设置在 0 到 24 的范围内 这是我的代码 j plot j placeholder d1 xaxis mode time min new Date 2010 11 01 getTime max new Date 2011

随机推荐