Skip to content

vue3 组件传参

1. 父 -> 子 defineProps

  • 父组件
vue
<template>
  <div>
    <Child :msg="msg" />
  </div>
</template>
  • 子组件
vue
<script setup>
defineProps({
  msg: {
    type: String,
    default: 'hello'
  }
})
</script>

2. 子 -> 父 defineEmits

  • 父组件
vue
<template>
  <div>
    <Child @change="handleClick" />
  </div>
</template>
<script setup>
import Child from './Child.vue'
const handleClick = (val) => {
  console.log('val')
} 
</script>
  • 子组件
vue
<script setup>
const emits = defineEmits(['change'])  // 定义事件
emits('change', 'hello')
</script>

3. 父 -> 子 useAttrs()

Vue3中,$attrs包含父组件中除props和自定义事件外的所有属性集合。(父组件传递的参数,defineProps()没接收的参数,都由useAttrs()接收)

  • 父组件
vue
<template>
  <div>
    <Child :msg="msg" data="123" name="王小二" />
  </div>
</template>
  • 子组件
vue
<script setup>
import { useAttrs } from 'vue'

// 接收父组件传递数据
const props = defineProps(['name'])

// 用VueUse方法获得,除props之外的参数
const attrs = useAttrs()
console.log(attrs)
</script>

4. 父 <-> 子 <-> 子 provideinject 多层,可双向

一个父组件相对于其所有的后代组件,会作为依赖提供者, 任何后代的组件树,无论层级有多深,都可以注入由父组件提供给整条链路的依赖。

  • 父组件
vue
<script setup>
import { ref, provide } from 'vue' 
const count = ref(0) 
provide('key', count)
</script>
  • 子组件 接收
vue
<script setup>
import { inject } from 'vue'
const count = inject('key') 
</script>

4.1. 应用层提供, 可以作为全局状态管理, 替代Pinia 或者 Vuex

  • useStore.js 状态管理
js
/**
 * 状态管理
 */
import { reactive } from "vue";
class useStore {
  state = reactive({
    loader: true,
  })
  /**
   * 设置loader
   * @param {*} state 状态
   */
  setLoader = state => {
    this.state.loader = state ? true : false;
  }
}
export default new useStore()
  • main.js 全局注入
js
import { createApp, provide } from 'vue'
import useStore from '@/hooks/useStore'

const app = createApp({
  setup() {
    provide('store', useStore)
    return () => h(App);
  }
})
  • 组件使用
vue
<script setup>
import { inject } from 'vue'
const store = inject('store')

store.setLoader(true); // 设置loader

let loading = computed(() => store.state.loader) // 获取loader
</script>

5. 父 -> 子 ref

  • 父组件
vue
<template>
  <div>
    <Child ref="child" />
  </div>
</template>
<script setup>
import { ref } from 'vue'
import Child from './Child.vue'

const child = ref(null) // 子组件实例

child.value.show() // 调用子组件方法
console.log(child.value.name) // 打印子组件实例

</script>
  • 子组件
vue
<script setup>
// 可以通过 defineExpose 编译器宏来显式指定在 <script setup> 组件中要暴露出去的属
defineExpose({
  name,
  show
})

const name = '王小二'
const show = () => {
  console.log('show')
} 
</script>

6. 父 <-> 子 v-model

vue
<template>
  <div>
    <Child v-model="msg" />
    <!-- 等同于 -->
    <Child :modelValue="msg" @update:modelValue="msg = $event" />
  </div>
</template>
vue
<script setup>
// 输入
const prop = defineProps({
  modelValue: String
})  
console.log(prop.modelValue)

// 输出
const emit = defineEmits(['update:modelValue'])
const change = () => {
  emit('update:modelValue', 'hello')
} 
</script>
defineModel 语法糖
  • 子 简化版
vue
<script setup>
const { modelValue, update: emit } = defineModel()
// 输入
console.log(modelValue)   // 等同于 prop.modelValue
// 输出
const change = () => {
  emit('hello')
} 
</script>

7. 其它

  • window 对象 绑定监听数据
  • 自定义事件 触发
  • 浏览器缓存

京ICP备2024093538号-1