vue3 组件学习

141 阅读1分钟
1.Props

可以以对象形式列出 prop,这些 property 的名称和值分别是 prop 各自的名称和类型:

props: {
  title: String,
  likes: Number,
  isPublished: Boolean,
  commentIds: Array,
  author: Object,
  callback: Function,
  contactsPromise: Promise // 或任何其他构造函数
}

父子组件传值例子 props父传子

子组件:

<template>
  <span>{{props.name}}</span>
  // 可省略【props.】
  <span>{{name}}</span>
</template>
<script setup>
  // import { defineProps } from 'vue'
  // defineProps在<script setup>中自动可用,无需导入
  // 需在.eslintrc.js文件中【globals】下配置【defineProps: true】

  // 声明props
  const props = defineProps({
     name: {
       type: String,
       default: ''
    }
  })  
</script>

父组件:

<template> 
   <child name='Jerry'/> 
</template> 
<script setup> 
   // 引入子组件 
   import child from './child.vue' 
</script>
2. 自定义事件

可以通过 emits 选项在组件上定义发出的事件。

父子组件传值例子

emit子传父

子组件:

<template> 
   <span>{{props.name}}</span>
   // 可省略【props.】 
   <span>{{name}}</span>
   <button @click='changeName'>更名</button> 
</template> 
<script setup> 
  // import { defineEmits, defineProps } from 'vue'
  // defineEmits和defineProps在<script setup>中自动可用,无需导入 
  // 需在.eslintrc.js文件中【globals】下配置【defineEmits: true】、【defineProps: true】 
  // 声明props 
  const props = defineProps({ name: { type: String, default: '' } }) 
  // 声明事件 
  const emit = defineEmits(['updateName']) 
  const changeName = () => { 
   // 执行 
   emit('updateName', 'Tom') 
  }
</script>

父组件:

<template>
   <child :name='state.name' @updateName='updateName'/>
</template>
<script setup>
    import { reactive } from 'vue'
    // 引入子组件
    import child from './child.vue'
    const state = reactive({ name: 'Jerry' })
    // 接收子组件触发的方法
    const updateName = (name) => {
        state.name = name
    }
</script>

v-model

支持绑定多个v-modelv-model 是 v-model:modelValue 的简写
绑定其他字段,如:v-model:name

子组件

<template>
  <span @click="changeInfo">我叫{{ modelValue }},今年{{ age }}岁</span>
</template>

<script setup>
  // import { defineEmits, defineProps } from 'vue'
  // defineEmits和defineProps在<script setup>中自动可用,无需导入
  // 需在.eslintrc.js文件中【globals】下配置【defineEmits: true】、【defineProps: true】
  defineProps({
    modelValue: String,
    age: Number
  })
  const emit = defineEmits(['update:modelValue', 'update:age'])
  const changeInfo = () => {
    // 触发父组件值更新
    emit('update:modelValue', 'Tom')
    emit('update:age', 30)
  }
</script>

父组件

<template> 
  // v-model:modelValue简写为v-model 
  // 可绑定多个v-model 
  <child v-model="state.name" v-model:age="state.age" />
</template>
<script setup> 
  import { reactive } from 'vue' 
  // 引入子组件 
  import child from './child.vue' 
  const state = reactive({ name: 'Jerry', age: 20 }) 
</script>
3. 插槽 slot

子组件

<template> 
  // 匿名插槽 
  <slot/> 
  // 具名插槽 
  <slot name='title'/> 
  // 作用域插槽 
  <slot name="footer" :scope="state" />
</template> 
<script setup> 
   import { useSlots, reactive } from 'vue' 
   const state = reactive({ name: '张三', age: '25岁' }) 
   const slots = useSlots() 
   // 匿名插槽使用情况 
   const defaultSlot = reactive(slots.default && slots.default().length) 
   console.log(defaultSlot) // 1 
   // 具名插槽使用情况 
   const titleSlot = reactive(slots.title && slots.title().length) 
   console.log(titleSlot) // 3 
</script>

父组件

<template> 
  <child> 
    // 匿名插槽 
    <span>我是默认插槽</span> 
    // 具名插槽 
    <template #title> 
       <h1>我是具名插槽</h1> 
       <h1>我是具名插槽</h1> 
       <h1>我是具名插槽</h1> 
    </template> 
    // 作用域插槽 
    <template #footer="{ scope }"> 
       <footer>作用域插槽——姓名:{{ scope.name }},年龄{{ scope.age }}</footer> 
    </template> 
  </child> 
</template> 
<script setup> 
  // 引入子组件 
  import child from './child.vue' 
</script>
4. provide/inject

父组件

<template> 
  <child/> 
</template> 
<script setup> 
  import { provide } from 'vue' 
  import { ref, watch } from 'vue' 
  // 引入子组件 
  import child from './child.vue' 
  let name = ref('Jerry') 
  // 声明provide 
  provide('provideState', { 
    name, 
    changeName: () => { 
    name.value = 'Tom' 
  } 
 }) 
// 监听name改变 
 watch(name, () => { 
  console.log(`name变成了${name}`) 
  setTimeout(() => { 
   console.log(name.value) // Tom 
   }, 1000) 
 }) 
</script>

子组件

<script setup> 
  import { inject } from 'vue' 
  // 注入 
  const provideState = inject('provideState') 
  // 子组件触发name改变 
  provideState.changeName() 
</script>