VUE中數據通信方式

準備

目錄結構
在這裏插入圖片描述
cli服務 npm i @vue/cli-service-global -g

入口文件main.js

import Vue from "vue";
import App from "./App"

new Vue({
    el:"#app",
    render:h=>h(App)
})

根組件APP.Vue.js

<template>
    <div>
        <parent></parent>
    </div>
</template>

<script>
import parent from "./components/parent"
export default{
    components: {
        parent
    }
}
</script>

組件通信

1. props

父組件通過props的方式向子組件傳遞數據,而通過$emit 子組件可以向父組件通信。

  • 父傳子

parent.vue

<template>
  <div>
    parent--->{{number}}
    <hr />
    <son :number = number @changeInParent="changeInParent"></son>
  </div>
</template>

<script>
import son from "./son";
export default {
  data() {
    return {
      number: 100
    };
  },
  methods: {
    changeInParent(newValue){
      this.number = newValue
    }
    
  },
  components: {
    son
  }
};
</script>

son.vue

<template>
  <div>
    <p>son--->{{number}}</p>
    <button @click ="changeInSon()" >change</button>
    <hr>
  </div>
</template>

<script>
export default {
  props: {
    number: Number
  },
  methods: {
    changeInSon() {
        this.$emit("changeInParent",200)
    }
  },
};
</script>

在這裏插入圖片描述
2. $emit

  • 父傳子,子傳孫
    在上面的基礎上加上grandson.vue組件,parent.vue不做修改

son.vue

<template>
  <div>
    <p>son--->{{number}}</p>
    <button @click ="changeInSon()" >change</button>
    <hr>
    <grandson :number = "number" @change="change"></grandson>
  </div>
</template>

<script>
import grandson from "./grandson"
export default {
  props: {
    number: Number
  },
  methods: {
    changeInSon() {
        this.$emit("changeInParent",200)
    },
    change(newValue){
        this.$emit("changeInParent",newValue)
    }
  },
  components:{
      grandson
  }
};
</script>

grandson.vue

<template>
  <div>
    <p>grandson--->{{number}}</p>
    <button @click="changeInGrandson()">change</button>
  </div>
</template>

<script>
export default {
  props: {
    number: Number
  },
  methods: {
      changeInGrandson(){
          this.$emit("change",300)
      }
  }
};
</script>

在這裏插入圖片描述
同步父子組件的數據=>語法糖的寫法
2.1. .sync/update

parent.vue

<template>
  <div>
    parent--->{{number}}
    <hr />
    <son :number = number @update:number="changeInParent"></son>  
  </div>
</template>

<script>
import son from "./son";
export default {
  data() {
    return {
      number: 100
    };
  },
  methods: {
     changeInParent(newValue){
       this.number = newValue
     }
  },
  components: {
    son
  }
};
</script>
</script>

以上還可以簡化爲:

parent.vue

<template>
  <div>
    parent--->{{number}}
    <hr />
    <!-- <son :number = number @update:number="newValue=>number = newValue"></son> -->
    <son :number.sync = number></son>
  </div>
</template>

<script>
import son from "./son";
export default {
  data() {
    return {
      number: 100
    };
  },
  components: {
    son
  }
};
</script>

son.vue

<template>
  <div>
    <p>son--->{{number}}</p>
    <button @click ="changeInSon()" >change</button>
    <hr>
  </div>
</template>

<script>
export default {
  props: {
    number:Number,
  },
  methods: {
    changeInSon() {
        this.$emit("update:number",600)
    },
  },
};
</script>

在這裏插入圖片描述
2.2 .v-model/input/value

v-mode只能給子組件傳遞一個屬性

parent.vue

<template>
  <div>
    parent--->{{number}}
    <hr />
    <!-- <son :value = number @input="newValue => number = newValue"></son> -->
    <son v-model="number"></son>
  </div>
</template>

<script>
import son from "./son";
export default {
  data() {
    return {
      number: 100
    };
  },
  components: {
    son
  }
};
</script>

son.vue

<template>
  <div>
    <p>son--->{{value}}</p>
    <button @click ="changeInSon()" >change</button>
    <hr>
  </div>
</template>

<script>
export default {
  props: {
    value: Number
  },
  methods: {
    changeInSon() {
        this.$emit("input",700)
    },
  },
};
</script>

在這裏插入圖片描述
3. $children/$parent

使用 this.$parent查找當前組件的父組件,可直接觸發父組件的父組件的方法
使用 this.$children查找當前組件的直接子組件,可以遍歷全部子組件,但$children 並不保證順序,也不是響應式的。

parent.vue

<template>
  <div>
    parent--->{{number}}
    <hr />
    <son :number = number @changeInParent="changeInParent"></son>
  </div>
</template>

<script>
import son from "./son";
export default {
  data() {
    return {
      number: 100
    };
  },
  methods: {
    changeInParent(newValue){
      this.number = newValue
    }
    
  },
  components: {
    son
  }
};
</script>

son.vue

<template>
  <div>
    <p>son--->{{number}}</p>
    <button @click ="changeInSon()" >change</button>
    <hr>
    <grandson :number = "number"></grandson>
  </div>
</template>

<script>
import grandson from "./grandson"
export default {
  props: {
    number: Number
  },
  methods: {
    changeInSon() {
        this.$emit("changeInParent",200)
    },
  },
  components:{
      grandson
  }
};
</script>

grandson.vue

<template>
  <div>
    <p>grandson--->{{number}}</p>
    <button @click="changeInGrandson()">change</button>
  </div>
</template>

<script>
export default {
  props: {
    number: Number
  },
  methods: {
      changeInGrandson(){
          this.$parent.$emit("changeInParent",400)
      }
  }
};
</script>

在這裏插入圖片描述
出現多層時使用 :$disptch/broadcast

如果層級很深就會出現$parent.$parent…這裏封裝一個$dispach方法進行向上派發

parent.vueson.vue較上一個案例不做修改,
main.js中定義一個dispatch方法,$dispatch可以逐級往上找父中的方法,
main.js中定義一個broadcast方法,broadcast可以逐級往上找父中的方法.

main.js

import Vue from "vue";
import App from "./App"

// 自己定義一個disptch方法
Vue.prototype.$dispatch = function(evenName,value){
    let parent = this.$parent;
    while(parent){
        parent.$emit(evenName,value)
        parent = parent.$parent
    }
}

new Vue({
    el:"#app",
    render:h=>h(App)
})

grandson.vue

<template>
  <div>
    <p>grandson--->{{number}}</p>
    <button @click="changeInGrandson()">change</button>
  </div>
</template>

<script>
export default {
  props: {
    number: Number
  },
  methods: {
      changeInGrandson(){
          this.$dispatch("changeInParent",500)
      }
  }
};
</script>

在這裏插入圖片描述
4.$attrs、 $listeners

$attrs、 $listeners均可跨級傳值

$attrs用來接收傳過來的多個屬性,跨級傳用 v-bind
$listeners用來接收傳過來的多個方法,跨級傳用 v-on

parent.vue

<template>
  <div>
    parent--->{{number}}--->{{sum}}
    <hr />
    <son :number="number" :sum="sum" @click="showclick" @mousedown="showmouse"></son>
  </div>
</template>

<script>
import son from "./son";
export default {
  data() {
    return {
      number: 100,
      sum: 0
    };
  },

  methods: {
    showclick() {
      window.console.log("clickEvent...");
    },
    showmouse(){
      window.console.log("mouseEvent...");
    }
  },
  components: {
    son
  }
};
</script>

son.vue

<template>
  <div>
    <p>son--->{{$attrs.number}}--->{{$attrs.sum}}</p>
    <hr>
    <grandson v-bind="$attrs" v-on = "$listeners" ></grandson>
  </div>
</template>

<script>
import grandson from "./grandson"
export default {
  inheritAttrs: false, //可以把傳遞過來的屬性不作爲標籤真正的屬性
  components:{
      grandson
  },
  
};
</script>

在這裏插入圖片描述
grandson.vue

<template>
  <div>
    <p>grandson--->{{$attrs}}</p>
    <p>grandson--->number:{{$attrs.number}}--->{{$attrs.sum}}</p>
    <button @click="$listeners.click()">triggerClickEvent</button>
    <br><br>
    <button @click="$listeners.mousedown()">triggerMouseEvent</button>
  </div>
</template>

在這裏插入圖片描述
5. Provide&Inject

數據比較多的情況下,不建議使用

Provide 在父級中提供數據

<template>
  <div>
    <parent></parent>
  </div>
</template>

<script>
import parent from "./components/parent";
export default {
  provide() {
    return {
      name: "wangcai"
    };
  },
  components: {
    parent
  }
};
</script>

Inject在任意子組件中可以注入父級數據

<template>
  <div>
    {{name}}
  </div>
</template>

<script>
export default {
  inject: ["name"],
};
</script>

6. ref/refs

獲取組件實例,在父組件中得到子組件,並且調用子組件的方法
利用ref給子組件起一個name,然後在父組件中利用this.$refs.name.alertINfo()去獲取子組件中的alertINfo()方法

parent.vue

<template>
  <div>
    <son ref="sonMethods"></son>
  </div>
</template>

<script>
import son from "./son";
export default {
  mounted() {
    this.$refs.sonMethods.alertINfo()
  },
  components: {
    son
  }
};
</script>

son.vue

<template>
  <div>
  </div>
</template>
<script>
export default {
  methods: {
    alertINfo() {
      window.console.log("this is a methods on son ......");
    }
  }
};
</script>

在這裏插入圖片描述
7. EventBus

事件總線,用於跨組件通知
在入口文件中將$bus掛載到Vue原型上
然後利用this.$bus.$on("event",function(){ })在父組件註冊事件
然後利用this.$bus.$emit("event")在子組件註冊事件

main.js

import Vue from "vue";
import App from "./App";
// 將$bus掛載到Vue原型上面的一個vm
Vue.prototype.$bus = new Vue()

new Vue({
  el: "#app",
  render: h => h(App)
});

parent.vue

<template>
  <div>
    <son></son>
  </div>
</template>
<script>
import son from "./son";
export default {
  mounted() {
    this.$bus.$on("change",function(){
       window.console.log("change...");
    })
  },
  components: {
    son
  }
};
</script>

grandson.vue

<template>
  <div>
  </div>
</template>

<script>
export default {
  mounted(){
    this.$nextTick(()=>{
            this.$bus.$emit("change")
        })
  }
};
</script>

在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章