0


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

一、属性传值——父传子

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

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

父组件App:

  1. <template>
  2. <div id="app">
  3. <Box v-for="(item, index) in arr"
  4. :key="item.id"
  5. :employee="item.employee"
  6. :salary="item.salary"></Box>
  7. <p>总工资:{{total}}</p>
  8. </div>
  9. </template>
  10. <script>
  11. import Box from "./Box.vue";
  12. export default {
  13. data() {
  14. return {
  15. arr: [
  16. { id: 1, employee: "haha", salary: 3221 },
  17. { id: 2, employee: "xixi", salary: 4262 },
  18. { id: 3, employee: "yoyo", salary: 3122 }
  19. ]
  20. };
  21. },
  22. components: {
  23. Box
  24. },
  25. computed:{
  26. total(){
  27. let sum=0
  28. for (let i = 0; i < this.arr.length; i++) {
  29. sum+=this.arr[i].salary
  30. }
  31. return sum
  32. }
  33. }
  34. };
  35. </script>

子组件Box:

  1. <template>
  2. <div>
  3. <span>员工:{{employee}} 工资:{{salary}}</span>
  4. <button @click="change">涨工资</button>
  5. </div>
  6. </template>
  7. <script>
  8. export default {
  9. props:["employee","salary"],
  10. methods:{
  11. change(){
  12. this.salary+=500
  13. }
  14. }
  15. }
  16. </script>

** 结果显示:**

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

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

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

父组件App:

  1. <template>
  2. <div id="app">
  3. <Box @mychange="fn" v-for="(item, i) in arr"
  4. :key="item.id"
  5. :employee="item.employee"
  6. :salary="item.salary"
  7. :index="i"></Box>
  8. <p>总工资:{{total}}</p>
  9. </div>
  10. </template>
  11. <script>
  12. import Box from "./Box.vue";
  13. export default {
  14. data() {
  15. return {
  16. arr: [
  17. { id: 1, employee: "haha", salary: 3221 },
  18. { id: 2, employee: "xixi", salary: 4262 },
  19. { id: 3, employee: "yoyo", salary: 3122 }
  20. ]
  21. };
  22. },
  23. components: {
  24. Box
  25. },
  26. methods:{
  27. fn(newsalary,index){
  28. //父组件接收到子组件传来的新值更新自己的数据 并重新传值 刷新页面
  29. this.arr[index].salary=newsalary
  30. this.$set(this.arr,index,this.arr[index])
  31. }
  32. },
  33. computed:{
  34. total(){
  35. let sum=0
  36. for (let i = 0; i < this.arr.length; i++) {
  37. sum+=this.arr[i].salary
  38. }
  39. return sum
  40. }
  41. }
  42. };
  43. </script>

子组件Box:

  1. <template>
  2. <div>
  3. <span>员工:{{employee}} 工资:{{salary}}</span>
  4. <button @click="change">涨工资</button>
  5. </div>
  6. </template>
  7. <script>
  8. export default {
  9. props:["employee","salary","index"],
  10. methods:{
  11. change(){
  12. let newsalary=this.salary+500
  13. //触发父组件的事件 同时将修改后的数据传给父组件
  14. this.$emit("mychange",newsalary,this.index)
  15. }
  16. }
  17. }
  18. </script>

** 结果显示: **

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

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

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

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

父组件App:

  1. <template>
  2. <div>
  3. <h1>app组件--{{msg}}</h1>
  4. <Box :a1.sync="msg"></Box>
  5. </div>
  6. </template>
  7. <script>
  8. import Box from "./Box.vue"
  9. export default {
  10. data() {
  11. return {
  12. msg: "app的数据",
  13. }
  14. },
  15. components: {
  16. Box
  17. },
  18. }
  19. </script>

子组件Box:

  1. <template>
  2. <div>
  3. <h2>box组件--a1--{{a1}}</h2>
  4. <button @click="change">修改a1中的数据</button>
  5. </div>
  6. </template>
  7. <script>
  8. export default {
  9. props:["a1"],
  10. methods:{
  11. change(){
  12. console.log("点击了按钮")
  13. // 由以下两步操作,变为了一步:
  14. //this.a1="box修改了a1的值"
  15. // this.$emit("myevent","box修改了a1的值")
  16. this.$emit("update:a1","box修改了a1的值")
  17. }
  18. }
  19. }
  20. </script>

**结果显示: **

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

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

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

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

父组件中:

  1. <template>
  2. <div class="app">
  3. <h2>app组件--{{msg}}</h2>
  4. <Box v-model="msg"></Box>
  5. </div>
  6. </template>
  7. <script>
  8. import Box from "./Box.vue"
  9. export default {
  10. data() {
  11. return {
  12. msg:"app组件的数据"
  13. }
  14. },
  15. components: {
  16. Box
  17. },
  18. methods:{
  19. }
  20. }
  21. </script>

子组件中:

  1. <template>
  2. <div class="box">
  3. <h2>box组件--{{value}}</h2>
  4. <button @click="change">change</button>
  5. </div>
  6. </template>
  7. <script>
  8. export default {
  9. props:["value"],
  10. methods:{
  11. change(){
  12. this.$emit("input","box修改了数据")
  13. }
  14. }
  15. }
  16. </script>

** 结果显示: **

v-model指令的修饰符:

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

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

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

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

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

  • 用户可能输入的字符串中含有空格,这样系统在处理时可能会出现错误。
  • 使用trim修饰符来去掉字符串首部或者尾部的所有空格。
  1. <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组件中:

  1. <template>
  2. <div>
  3. <h1>app-{{msg}}</h1>
  4. <button @click="change1">点击修改app组件的msg</button>
  5. <Box1 :b1="msg" @x="xchange"></Box1>
  6. </div>
  7. </template>
  8. <script>
  9. import Box1 from "./Box1.vue"
  10. export default {
  11. data() {
  12. return {
  13. msg: "app组件的数据"
  14. }
  15. },
  16. methods:{
  17. change1(){
  18. this.msg="app组件修改了msg的数据"
  19. },
  20. xchange(arg){
  21. this.msg=arg
  22. }
  23. },
  24. components:{
  25. Box1
  26. }
  27. }
  28. </script>

Box1组件中:

  1. <template>
  2. <div>
  3. <h1>{{$attrs.b1}}</h1>
  4. <Box2 v-bind="$attrs" v-on="$listeners"></Box2>
  5. </div>
  6. </template>
  7. <script>
  8. import Box2 from "./Box2.vue"
  9. export default {
  10. components:{
  11. Box2
  12. },
  13. methods:{
  14. look(){
  15. console.log(this.$attrs)
  16. }
  17. }
  18. }
  19. </script>

Box2组件中:

  1. <template>
  2. <div>
  3. <h3>box2--{{b1}}</h3>
  4. <button @click="change">change</button>
  5. </div>
  6. </template>
  7. <script>
  8. export default {
  9. props:["b1"],
  10. methods:{
  11. change(){
  12. this.$emit("x","box2修改了数据")
  13. }
  14. }
  15. }
  16. </script>

结果显示:

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

$root: 访问根组件vm对象,所有的子组件都可以将这个实例作为一个全局 store 来访问或使用,现在有更好的技术vuex代替。

$parent:访问父组件对象,直接操作父组件的data数据,不需要再使用属性传值,但是容易出现渲染混乱之后只渲染一个的情况 可以连点 this.parent.parent...

$children:访问子组件对象数组,不是子元素 不能保证顺序,没有按照顺序加载,加载顺序是混乱的也不是响应式的

$refs:只会在组件渲染完成之后生效,并且它们不是响应式的。应该避免在模板或计算属性中访问 $refs。在组件或者原生元素绑定ref属性(类似于id) 在父组件中可以通过 this.$refs访问到它

App组件:

  1. <template>
  2. <div>
  3. <h1>app组件--{{msg}}</h1>
  4. <div>
  5. <Box1></Box1>
  6. <!--虽然Box1组件写在div里面 但是.$parent指的还是父组件App 而非div-->
  7. </div>
  8. </div>
  9. </template>
  10. <script>
  11. import Box1 from "./Box1.vue"
  12. export default {
  13. data() {
  14. return {
  15. msg:"app组件的数据"
  16. }
  17. },
  18. methods: {},
  19. components: {
  20. Box1
  21. }
  22. }
  23. </script>

Box1组件:

  1. <template>
  2. <div>
  3. <button @click="look">box1</button>
  4. <Box2></Box2>
  5. <Box2></Box2>
  6. <p ref="p1">ref</p>
  7. <button @click="getref">获取ref</button>
  8. </div>
  9. </template>
  10. <script>
  11. import Box2 from "./Box2.vue"
  12. export default {
  13. components: {
  14. Box2
  15. },
  16. methods: {
  17. getref(){
  18. console.log(this.$refs)
  19. },
  20. look() {
  21. console.log(this,this.$parent,this.$children,this.$root)
  22. this.$parent.msg="box1修改了app的数据"
  23. }
  24. }
  25. }
  26. </script>

Box2组件:

  1. <template>
  2. <div>
  3. <p>{{$parent.$parent.msg}}</p>
  4. <button @click="change1">box2-change</button>
  5. </div>
  6. </template>
  7. <script>
  8. export default {
  9. methods:{
  10. change1(){
  11. this.$parent.$parent.msg="box2修改了数据"
  12. }
  13. }
  14. }
  15. </script>

结果显示:

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

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

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

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

  1. // provide选项提供变量
  2. provide: {
  3. message: 'provided by father'
  4. },
  1. 子孙组件使用: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:

  1. Vue.prototype.$bus = new Vue({
  2. methods: {
  3. //绑定事件
  4. on(eventname, callback) {
  5. this.$on(eventname, callback)
  6. },
  7. //触发事件
  8. emit(eventname, ...arg) {
  9. this.$emit(eventname, ...arg)
  10. },
  11. //解绑事件
  12. off(eventname, callback) {
  13. this.$off(eventname, callback)
  14. },
  15. }
  16. })

使用:

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


本文转载自: https://blog.csdn.net/qq_56668869/article/details/126740987
版权归原作者 哈哈ha~ 所有, 如有侵权,请联系我们删除。

“vue&mdash;&mdash;组件传值(高级)、属性传值、反向传值、跨级传值”的评论:

还没有评论