V3-define系列: defineProps | defineEmits | defineExpose | defineModel等

152 阅读2分钟
1.defineProps的用法
// 父组件
<Child v-model:parentModel =textVal  v-model=textVal ref="child" @myClick='myClick'></Child>

// 子组件
// 方式1 接收父组件 props 属性
const props = defineProps({
  modelValue: {
    default: 0,
    require: true
  },
  parentModel: {
    default: 0,
    require: true
  }
})
// 方式二 
const props = defineProps<{
    modelValue:string,
    parentModel: string
}>()
2. defineComponent 自定义组件
// 创建自定义自建
defineComponent({
  props:{},
  setup(props, context) {},
  methods:{},
  template: `
    <div>{{}}</div>
  `
}) 
3.defineEmits的用法
// 子组件中 声明一下 父组件暴露的方法 或 事件名, 
const emit = defineEmits(['update:modelValue', 'update:parentModel''myClick'])
4.defineExpose({}) 子组件数据暴露给父亲组件ref(dom)内直接使用
// 子组件
const childData = ref(999)
defineExpose({childData}) // 对象形式暴露出去

// 父组件 
// js中
const child = ref() // 抓取dom
onMounted(() => {
  nextTick(() => {
    // 必须确保自组件数据挂在完成后获取,否则娶不到
    console.log(child?.value?.childData)
  })
})

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

5.vue3.3 新增 (defineModel | defineOptions) | defineSolts(Ts)
--- defineModel相关用法

Tip:vue3.3 新增的 defineMode 默认是关闭状态,必须vite.config.ts 配置开启才能使用

// 很重要很重要很重要:
// vite.config.ts 中
plugins: [
    vue({
      script: {
        defineModel: true // 必须打开defineModel 才能使用
      }
    })
  ],

// 父组件中 随便定义2个绑定数据
import Child from '../components/Child.vue' // 子组件
const textVal = reactive({
  name: 11
})
const child = ref('defineModel-parentModel')
 <Child v-model:parentModel = "child"  v-model="textVal.name" ></Child>


// Child- 子组件中
import { defineModel } from 'vue'
const inputVal1 = defineModel('modelValue') // 默认取 modelValue 或者不传 defineModel()
const inputVal2 = defineModel('parentModel') //  onupdate名
console.log(inputVal1.value) // 父组件传过来的默认值
console.log(inputVal2.value) // // 父组件传过来的默认值
// 点击改变父组件中数据 或者 v-model 绑定均可
const clickBtn = () => { // 等同于 默认触发 update:modelValue
  inputVal1.value = 888
  inputVal2.value = 999
}

// Child-template中
    Child组件:
    <!-- 子组件改变父组件数据 tip: 仅支持 vue3.3+ -->
    <input type="text" v-model="inputVal1">
    <input type="text" v-model="inputVal2">
    <button @click="clickBtn">点醒你</button>
----defineOptions()
// vue3.3 以上 声明组件选项  setup 语法糖 和 非setup 合并到一个script 中
// Tip: 注意此处的执行顺序
// Tip: 注意此处的执行顺序
// Tip: 注意此处的执行顺序
defineOptions({
  name: 'child',
  inheritAttrs:false, // 是否属性继承
  components: {
    
  },
  mounted() {
    console.log('options-mounted')
  }
})
onMounted(() => {
  console.log('onMounted')
})
打印如下:
// onMounted  先被打印
// options-mounted
---- slot | useSlots() | defineSlots 的用法
// 父组件
<Child v-model:parentModel = "child"  v-model="textVal.name">
    <template #lyon1> // 指定某个名称的插槽
      <div>
        slot1-lyon1
      </div>
    </template>
    <template #lyon2>
      <div>
        slot2-lyon2
      </div>
    </template>
  </Child>
  
 // 子组件
方法1:  
const slot =  useSlots() // 插槽集 默认default:()=>{}
console.log("slot")
console.log(slot) // {lyon1: ()=>{}} {lyon2: ()=>{}} 
console.log(slot.lyon1);
方法2:
// Ts 声明 插槽方式
const slots = defineSlots<{
  default:(props: string) => any,
  lyon1: (props: string) => any,
  lyon2:(props:string) => any
}>()
console.log(slots); // 打印同于 useSlots() 返回值
    // Child template组件:
    <h1>Slot插槽:</h1>
    <slot name="lyon1"></slot>
    <slot name="lyon2"></slot>