vue3筆記 - 父子組件通信

父傳子

說明:父組件將數據綁定在組件標籤上;子組件props接收

父組件:

<template>
  <Child :msg="msg" />
</template>

<script setup>
import Child from './child.vue'
import { ref } from 'vue'

const msg = ref('hello world')
</script>

子組件,使用defineProps接收:

<template>
  <div>收到父組件傳的值:{{ msg }}</div>
</template>

<script setup>
const props = defineProps({
  msg: {
    type: String
  }
})
</script>

 

子傳父

說明:父組件定義自定義事件,綁定在子組件標籤上;子組件使用emit,觸發方法、傳值

父組件:

<template>
  <Child @addCount="addCount" @resetCount="resetCount" />
  <div>count: {{ count }}</div>
</template>

<script setup>
import { ref } from 'vue'
import Child from './child.vue'

let count = ref(0)

function addCount(e) {
  count.value += e
}

function resetCount() {
  count.value = 0
}
</script>

子組件使用defineEmits聲明事件:

<template>
  <el-button type="primary" @click="addCount">累加count</el-button>
  <el-button type="primary" @click="resetCount">重置count</el-button>
</template>

<script setup>
import { defineEmits } from 'vue'

const emit = defineEmits(['addCount', 'resetCount'])

function addCount() {
  emit('addCount', 22)
}

function resetCount() {
  emit('resetCount')
}
</script>

 

子組件直接修改父組件傳過來的值

父組件:

vue2如果想讓子組件能直接修改數據,使用的是.sync, vue3 使用v-model

<template>
  <Child  v-model:count="count" />
  <div>count: {{ count }}</div>
</template>

<script setup>
import { ref } from 'vue'
import Child from './child.vue'

let count = ref(0)
</script>

子組件:

需要聲明一個 update:count 事件

<template>
  <el-button type="primary" @click="updateCount">修改count</el-button>

</template>

<script setup>
import { defineEmits } from 'vue'

const props = defineProps({
  count: {
    type: Number
  }
})
const emit = defineEmits(['addCount', 'resetCount', 'update:count'])

function updateCount() {
  emit('update:count', 100)
}
</script>

 

defineExpose

使用<script setup>的組件,不會暴露任何聲明的變量屬性,也就是無法向vue2中:this.$refs.child.data類似這樣獲取數據

如果想操作,可以使用defineExpose來顯式的指定出,需要暴露出去的屬性

父組件:

<template>
  <el-button type="warning" @click="getChildVal">獲取子組件中的值</el-button>
  <div>{{ childMsg }}</div>

  <el-button type="primary" @click="runChildFunc">執行子組件的方法</el-button>

  <child ref="child" />
</template>

<script setup>
import { ref } from 'vue'
import Child from './child.vue'

// 必須跟子組件 ref  保持一致
const child = ref(null)
const childMsg = ref('')

// 獲取子組件的數據
function getChildVal() {
  childMsg.value = child.value.msg
}

// 執行子組件的方法
function runChildFunc() {
  child.value.testFunc()
}
</script>

子組件需要使用defineExpose暴露變量和方法:

<template>
  <div v-if="isShow">被父組件執行了,你個吊毛</div>
</template>

<script setup>
import { ref } from 'vue'

const msg = ref('在座的各位都是辣雞!!!')
const isShow = ref(false)

const testFunc = function () {
  isShow.value = !isShow.value
}

defineExpose({
  msg,
  testFunc
})
</script>

 

ref屬性

使用ref獲取DOM或者組件實例

與vue2寫法的區別,vue2中:

this.$refs.child.data

vue3沒有this,需要聲明一個 和 標籤ref保持一致的響應式變量,進行操作;如果想獲取子組件的數據,可以看上面的defineExpose

  • 操作單個組件 或者 DOM
<template>
  <child ref="child" />
</template>

<script setup>
import Child from './child.vue'

// 變量名稱必須跟子組件 ref  保持一致
const child = ref()

// 如果想獲取子組件的數據,可以看上面的defineExpose
console.log(child.value)
console.log(child.value.msg)
</script>
  • 操作多個DOM

定義一個函數,動態綁定到ref上即可

<template>
  <ul>
    <li v-for="item in 10" :ref="setRef">{{ item }}</li>
  </ul>
</template>

<script setup>
const setRef = (el) => {
  console.log(el)
}
</script>

上面寫法不太好區分某個DOM,也可以寫成如下:

<template>
  <ul>
    <li v-for="item in 10" :ref="el => setRef(el, item)">{{ item }}</li>
  </ul>
</template>

<script setup>
const setRef = (el, item) => {
  console.log(el, item)
}
</script>

 

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