vue中的define函数

defineAsyncComponent

异步加载组件的应用场景非常广泛,特别是在多页面应用中,常常需要根据用户需求动态加载不同的页面组件。除此之外,Vue3还支持了使用defineAsyncComponent函数来异步加载指令、插件、模板等其他各种组件。

通常

const HelloWorld=defineComponent(()=>
    import('../../components/HelloWorld.vue')
)

高级一点

// with options 
const AsyncPopup = defineAsyncComponent({ 
  loader: () => import("../......vue"),
  loadingComponent: LoadingComponent, /* 在加载时显示 */
  errorComponent: ErrorComponent, /* 显示是否有错误 */
  delay: 1000, /* 在显示加载组件之前延迟毫秒 */
  timeout: 3000 /* 这个毫秒之后的超时 */
})

defineComponent

一般是在ts或者tsx文件中使用

在这种情况下,我们需要defineComponent来帮我们做内部的一些options的提示

 
    import { defineComponent } from 'vue'
 
    export default defineComponent({
      name: 'Test',
      props:{
        data: String,
      },
      template:''
      setup(props, context){
        // props.data
        // context.attrs    context.slots    context.emit 
        return ...
      },
      ...
    })

defineCustomElement

参考官网

默认情况下,Vue 会将任何非原生的 HTML 标签优先当作 Vue 组件处理,而将“渲染一个自定义元素”作为后备选项。这会在开发时导致 Vue 抛出一个“解析组件失败”的警告。要让 Vue 知晓特定元素应该被视为自定义元素并跳过组件解析

// vite.config.js
import vue from '@vitejs/plugin-vue'

export default {
  plugins: [
    vue({
      template: {
        compilerOptions: {
          // 将所有带短横线的标签名都视为自定义元素
          isCustomElement: (tag) => tag.includes('-')
        }
      }
    })
  ]
}

接收的参数和 defineComponent 完全相同,但是他还多了styles参数

import { defineCustomElement } from 'vue'

const MyVueElement = defineCustomElement({
  ...
  template: `<div>{{title}}</div>`,

  // defineCustomElement 特有的:注入进 shadow root 的 CSS,行内样式
  styles: [`
    div {
      color: red
    }
  `]
})

// 注册自定义元素
// 注册之后,所有此页面中的 `<my-vue-element>` 标签
// 都会被升级
customElements.define('my-vue-element', MyVueElement)

export default MyVueElement

defineSSRCustomElement

.....官网api都没搜到,推测跟上面那个差不多但是是服务器端的

defineEmits和defineProps

defineEmits类似于组件上的@click、@change ......等固有方法(子组件需要一个或多个自定义方法,父组件提供给他),可以根据子组件提供的值修改父组件

defineProps类似于组件上的一些参数,如class,name.......,他不能直接修改(props.abc=abc会报错)

.............................子组件.......................................

<script setup lang="ts">
import { ref } from 'vue'

//定义组件参数
const props = defineProps({
    str: {
        type: String,
        default: '123',
        reqiured:true
    }
})

const sstr = ref(props.str)
//一般是这样写
// const emit = defineEmits([
//     'add1'
// ])

//但是这样可以定义该函数返回类型
const emit = defineEmits<{ (e: 'add1'): void, }>()

const changeValue = () => {
    emit('add1')
}

</script>
<template>
    <button @click="changeValue">{{ sstr }}</button>
</template>

 ............................父组件..............................

<script setup lang="ts">
import ZuJianChuanZhi from "../../components/ZuJianChuanZhi.vue"
import { ref } from "vue"

//上级组件的传参
import { useRoute } from "vue-router";
const route = useRoute()
const btnValue = ref(route.query.str ? route.query.str.toString() : '没有参数传递')



const addStr = () => {
    console.log('使用了emit');
}
</script>

<template>
    <ZuJianChuanZhi :str="btnValue" @add1="addStr" />
</template>

defineExpose

可以暴露子组件的属性和方法,父组件用ref去使用

子组件

/**
 * defineExpose
*/
const count = ref(0);
function increment() {
    count.value++;
}
defineExpose({
    count,
    increment,
})

父组件

<script setup lang="ts">
import ZuJianChuanZhi from "../../components/ZuJianChuanZhi.vue"
import { ref } from "vue"
const addStr = () => {
    console.log('使用了emit');
}

const childRef = ref()

//这里不要慌直接赋值childRef.value.count,加载组件时,子组件还没创建好,要报错,
//也不要直接把childRef.value.count绑定上去,原因和上面一样
const count = ref(0)

const addCount = () => {
    if (childRef.value) {
        childRef.value.increment()
        //这里单独使count.value++无法改变子组件中count的值
        count.value = childRef.value.count
    }
}

</script>
<template>
    <ZuJianChuanZhi ref="childRef" />
    <button @click="addCount">count:{{ count }}</button>
</template>

defineOptions

vue3.3及以上才能用

在选项式api中组件有name等一些属性,其他属性props,emits等都有相应的define方法,这个也有

<script setup lang="ts">
defineOptions({
  name: '组件名称'
  inheritAttrs: false, // 组件标签上的属性是否透传
  customOptions: {
    /* 其他配置 */
  }
})
</script>

defineModel

使用props时,在父组件改变传入的值,子组件改变不不了,这时候就要用到defineModel了

子组件

<script setup lang="ts">
import { ref } from 'vue'
/**
 * defineProps
*/
const props = defineProps({
    str: {
        type: String,
        default: '123',

    }
})
const sstr = ref(props.str)


/**
 * defineModel
 */
const model = defineModel()
console.log(model);

</script>
<template>
    <button @click="changeValue">{{ sstr }}</button>
    <input type="text" v-model="model" width="20px">
</template>

父组件

<script setup lang="ts">
import ZuJianChuanZhi from "../../components/ZuJianChuanZhi.vue"
import { ref, } from "vue"
import { useRoute } from "vue-router";

const route = useRoute()
const btnValue = ref(route.query.str ? route.query.str.toString() : '没有参数传递')
// 这里就简单把input的值加在按钮参数后面

const childRef = ref()
const count = ref(0)


const inputValue = ref('132')
const cli = () => {
    inputValue.value = (inputValue.value == '123' ? '321' : '123')
    btnValue.value = (inputValue.value == '123' ? '321' : '123')//没有变化
}
</script>

<template>
    <button @click="cli">click</button>
    <ZuJianChuanZhi :str="btnValue" v-model="inputValue" />
</template>

---------------------------------------------------

他还可以定义参数的类型,名字等,用法和defineProps一样

参考这里

defineSlots

仅限与ts使用,vue3.3+

我们可以使用 defineSlots 自己定义插槽的类型。这个宏在简单的组件中几乎用不到,但对于一些复杂的组件非常有用,尤其是这个特性与泛型组件一起使用。或是在 Volar 无法正确地推测出类型时,我们可以手动指定

<script setup lang="ts">
const slots = defineSlots<{
  // key > default 是插槽名称
  // 值类型是插槽函数
    // 函数的第一个TS对象类型参数是插槽期望接收的 props 的TS类型
    // 返回值类型目前被忽略,可以是 any,但官方说将来可能会利用它来检查插槽内容。
  default(props: { msg: string }): any
}>()
</script>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值