vue組件相關props,$parents , $children, $refs , provide / inject 使用

組件基本需要這三部分組成

props(屬性)

event(事件)

slot(插槽)

父子組件通信

# App.vue (父組件)
<template>
  <div id="app">
    <Child :msg="messsage" :model="obj" :myArr="arr"/>
  </div>
</template>
<script>
import Child from './components/Child'
export default {
  name: 'app',
  components: {
    Child
  },
  data(){
    return{
      messsage:'我是父組件的數據',
      obj:{
        name: "hello",
        age:15,
      },
      arr:[1,2,3,4],
    }
  }
}
</script>

# Child.vue (子組件)

<template>
  <div>
    <h1>{{ msg }}</h1>
    <h2>{{ model.name }} - {{model.age}}</h2>
    <ul>
      <li v-for="(item,index) in myArr" :key="index">
        {{item}}
      </li>
    </ul>
  </div>
</template>
<script>
export default {
  // props 裏 推薦使用對象寫法,用於組件的數據結構校驗
  /** 父子組件傳值 */
  props: { 
    // 父組件傳入的屬性是一個基本數據類型
    msg: { 
      type: String,
      default: '',
    },
    // 父組件傳入的屬性是一個對象
    model: {
      type: Object,
      default: () => {},
      required:true,
    },
    // 父組件 傳入 一個數組
    myArr:{
      type:Array,
      default:() => [],
    }
  }
}
</script>

<style scoped>
</style>

子向父組件通信 ( $on, $emit)


# 子組件 Child.vue

<template>
  <div>
    <h1>{{ msg }}</h1>
    <button @click="changeHandle">change父組件的值</button>
  </div>
</template>
<script>
export default {
  props: { 
    msg: { 
      type: String,
      default: '',
    },
  },
  methods:{
    changeHandle(){
      this.$emit("changeParent","我是子組件的值")
    }
  }
}
</script>



# 父組件 App.vue

<template>
  <div id="app">
    <Child @changeParent="getChildData" :msg="messsage"/>
  </div>
</template>
<script>
import Child from './components/Child'
export default {
  name: 'app',
  components: {
    Child
  },
  data(){
    return{
      messsage:'我是父組件的數據',
    }
  },
  methods:{
    getChildData(params){
      this.messsage = params;
    }
  }
}
</script>

子組件通過 $parent 獲取父組件的數據

# Child.vue (子組件)
<template>
  <div>
     <!-- this.$parent.messsage -->
    <h1>{{ this.$parent.messsage }}</h1>
      
    <button @click="changeHandle">change父組件的值</button>
  </div>
</template>
<script>
export default {
  props: { 
    msg: { 
      type: String,
      default: '',
    },
  },
  methods:{
    changeHandle(){
      this.$emit("changeParent","我是子組件的值")
    }
  }
}
</script>


# App.vue (父組件)
<template>
  <div id="app">
    <Child @changeParent="getChildData" :msg="messsage"/>
  </div>
</template>
<script>
import Child from './components/Child'
export default {
  name: 'app',
  components: {
    Child
  },
  data(){
    return{
      messsage:'我是父組件的數據',
    }
  },
  methods:{
    getChildData(params){
      this.messsage = params;
    }
  }
}
</script>

父組件通過($children) 獲取子組件的值

# App.vue (父組件)
<template>
  <div id="app">
    <h1>{{messsage}}</h1>
    <Child :msg="messsage"/>
    <!-- <Other :msg="messsage"/> -->
    <p>{{leader}}</p>
  </div>
</template>
<script>
import Child from './components/Child'
// import Other from './components/Other'
export default {
  name: 'app',
  components: {
    Child,
    // Other,
  },
  data(){
    return{
      messsage:'我是父組件的數據',
      leader:'',
    }
  },
  mounted(){
    this.$children.map(res=>{
      console.log(res)
     this.leader = res.miss
    })
  }
}
</script>

# Child.vue(子組件1)
<template>
  <div>
    <Other/>
    <button @click="changeHandle">change父組件的值</button>
  </div>
</template>
<script>
import Other from './Other'
export default {
  components:{
    Other,
  },
  props: { 
    msg: { 
      type: String,
      default: '',
    },
  },
  data(){
    return{
      message:"我是子組件的值",
      miss:'我是Child'
    }
  },
  methods:{
    changeHandle(){
      this.message = "hello"
    }
  }
}
</script>

# Other.vue(子組件2)
<template>
  <div>
    <h3>我是other</h3>
  </div>
</template>

<script>
  export default {
    data(){
      return{
        miss:'我是other組件'
      }
    }
  }
</script>

響應動態數據的變化

# App.vue (父組件)
<template>
  <div id="app">
    <Child :msg="Arr" />
    <button @click="changeHandle">點擊改變子組件中渲染的值 </button>
  </div>
</template>
<script>
import Child from './components/Child'

export default {
  name: 'app',
  components: {
    Child,
  },
  data() {
    return {
      messsage: '我是父組件的數據',
      num: 1,
      Arr:[1,2,3,4],
    }
  },
  methods: {
    changeHandle() {
      this.$set(this.Arr,2,{a:1})
    }
  }
}
</script>


# Child.vue (子組件)
<template>
  <div>
    <ul>
      <li v-for="(item,index) in msg" :key="index">{{item}}</li>
    </ul>
  </div>
</template>
<script>
export default {
  props: { 
    msg: { 
      type: Array,
      default: ()=>[],
    },
  },
  // 這個版本現在不需要作監聽也能響應父組件動態數據的變化了(以前是不行的)
  watch:{ 
    msg(oldValue,newValue){
      console.log(newValue);
    }
  },
  data(){
    return{
      message:"我是子組件的值",
    }
  },
  methods:{
    changeHandle(){
      
    }
  }
}
</script>

一種無依賴的組件通信:provide / inject 接口

# App.vue
<template>
  <div>
    app
    <Brother />
    <Child />
  </div>
</template>
<script>
import Brother from './components/Brother'
import Child from './components/Child'
export default {
  components: {
    Brother,
    Child,
  },
  provide: {
    name: 'App父組件的值'
  },
  data() {
    return {

    }
  }
}
</script>

<style scoped>
</style>


# Child.vue

<template>
  <div>
    Child組件
    {{name}}
  </div>
</template>

<script>
  export default {
    inject: ['name'],
    data(){
      return{

      }
    }
  }
</script>

<style scoped>

</style>


# Brother.vue

<template>
  <div>
    兄弟組件
    {{this.name}}
    <Child/>
  </div>
</template>

<script>
import Child from "./Child";
  
export default {
   components:{
      Child
    },
  data() {
    return {
      msg:'',
    }
  },
  inject: ['name'],
}
</script>

<style scoped>
</style>

Vue 官方提示:provide 和 inject 綁定並不是可響應的。這是刻意爲之的。然而,如果你傳入了一個可監聽的對象,那麼其對象的屬性還是可響應的

通過 $refs 獲取子組件的值

此方法只能獲取值,不能響應數據變化

# App.vue
<template>
  <div>
    <Brother ref="brother"/>
    {{myda}}
  </div>
</template>
<script>
import Brother from './components/Brother'

export default {
  components: {
    Brother,
  },
  data(){
   return{
      myda:"",
   }
  },
  mounted(){
    this.myda = this.$refs.brother.msg
  },
}
</script>

# Brother.vue
<template>
  <div>
    兄弟組件
  </div>
</template>
<script>
export default {
  data() {
    return {
      msg:'我是Brother組件',
    }
  }
}
</script>

兄弟組件通信(同樣適用於跨級組件通信)

//中央事件總線
var bus=new Vue();

// 還是利用 $on 和 $emit 的監聽和發射
var app=new Vue({
    el:'#app',
    template:`
    <div>
        <A1></A1>
        <A2></A2>
    </div>
`
})

// 在組件 A1 的 methods 方法中觸發事件
bus.$emit('say-hello', 'world')

// 在組件 A2 的 created 鉤子函數中監聽事件
bus.$on('say-hello', function (arg) {
  console.log('hello ' + arg);          // hello world
})



插槽 .... 略過,已經寫過如何使用!
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章