• vue3+ts组件练习(defineExpose defineEmits defineProps)


    学习关键语句:
    vue3+ts 组件写法

    写在前面

    进化到 vue3 + ts 的时代,vue的不少语法发生了改变,尤其是选项式 API 变为了组合式 API 和 typescript 的使用使得从 vue2 过来的人需要尽快熟悉新的写法,毕竟大差不差嘛

    文章最后有本文使用项目文件链接

    这篇文章练习的点共有三个:

    defineExpose => 组件向外暴露的自身的属性和方法

    defineEmits => 组件向外暴露的自定义方法

    defineProps => 组件可以传入的值

    我们将一个一个来练习使用

    开始

    我们先使用 vite 创建一个工程项目 我起名为 practice-app

    npm create vite
    
    • 1

    如下图选择就可以完成创建,再根据提示 cd practice-app 安装依赖之后就可以运行了
    在这里插入图片描述
    接下来,打开项目目录 src 打开 App.vue 将里面的内容替换成空白
    在这里插入图片描述
    在这里插入图片描述
    之所有会有样式是因为引入了 src 下的 style.css 文件,如果你不感冒,可以清空里面的样式,作为练习我无动于衷(™这是在说啥)

    创建一个测试用例组件

    在 components 文件下新建文件 YaHooTest.vue
    写一点基础的东西,然后就在 App.vue 文件引入后就准备开始练习了
    在这里插入图片描述
    在这里插入图片描述

    defineExpose

    defineExpose 可以向外暴露组件的属性值和方法,我们一个一个来测试

    属性值

    我们先简单写好一个输入框,将输入框的值作为向外暴露的属性值

    App.vue

    <template>
      <h1>hello 邵雅虎</h1>
      <hr>
      <ya-hoo-test ref="testRef"></ya-hoo-test>
      <br>
      <button @click="conInput">打印输入框的内容</button>
    </template>
    
    <script setup lang="ts">
    import { ref } from 'vue' 
    import YaHooTest from './components/YaHooTest.vue';
    
    const testRef = ref(null)
    const conInput = () => {
      console.log(testRef.value.txt)
    }
    </script>
    
    <style scoped>
    
    </style>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    YaHooTest.vue

    <template>
      <div>你好,邵雅虎</div>
      输入框:<input type="text" v-model="txt">
    </template>
    
    <script setup lang="ts">
    import { ref } from 'vue' 
    
    let txt = ref('')
    
    defineExpose({
      txt
    })
    </script>
    
    <style scoped>
    
    </style>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    在这里插入图片描述
    在这里插入图片描述
    这个文字内容完全是属于组件的一部分,和父组件是一点关系都没有,但是通过 defineExpose 的方式可以将子组件的属性值进行显示

    方法

    那么我们接下来向外暴露方法

    我们简单写一个 显示/隐藏 子组件内容人物信息卡的方法,其中,人物信息卡的内容我们暂时写死,之后再通过 defineProps 从父组件获取

    App.vue

    <template>
      <h1>hello 邵雅虎</h1>
      <hr>
      <ya-hoo-test ref="testRef"></ya-hoo-test>
      <br>
      <button @click="conInput">打印输入框的内容顺便打开人物信息卡</button>
    </template>
    
    <script setup lang="ts">
    import { ref } from 'vue' 
    import YaHooTest from './components/YaHooTest.vue';
    
    const testRef = ref(null)
    const conInput = () => {
      console.log(testRef.value.txt)
      testRef.value.openPerson()
    }
    </script>
    
    <style scoped>
    
    </style>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    YaHooTest.vue

    <template>
      <div>你好,邵雅虎</div>
      <div v-if="showPerson" style="backgroundColor:black;color:white">
        <h3>人物信息卡</h3>
        <h5>姓名:邵雅虎</h5>
        <h5>年龄:18</h5>
        <h5>爱好:唱、跳、rap</h5>
        <button @click="closePerson">关闭</button>
      </div>
      输入框:<input type="text" v-model="txt">
    </template>
    
    <script setup lang="ts">
    import { ref } from 'vue'
    
    let txt = ref('')
    let showPerson = ref(false)
    // 打开人物信息卡
    const openPerson = () => {
      showPerson.value = true
    }
    // 关闭人物信息卡
    const closePerson = () => {
      showPerson.value = false
    }
    
    defineExpose({
      txt,
      openPerson
    })
    </script>
    
    <style scoped>
    
    </style>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36

    在这里插入图片描述
    这样一来就可以通过子组件提供的方法来打开人物信息卡了
    在这里插入图片描述

    defineProps

    接下来我们来测试 defineProps 这个东东
    我们将之前的人物信息卡里面的信息通过父组件传递进来

    App.vue

    <template>
      <h1>hello 邵雅虎</h1>
      <hr>
      <ya-hoo-test ref="testRef" :person="p"></ya-hoo-test>
      <br>
      <button @click="conInput">打印输入框的内容顺便打开人物信息卡</button>
    </template>
    
    <script setup lang="ts">
    import { ref } from 'vue'
    import YaHooTest, { Person } from './components/YaHooTest.vue';
    
    const testRef = ref(null)
    const conInput = () => {
      console.log(testRef.value.txt)
      testRef.value.openPerson()
    }
    let p: Person = {
      name: '邵雅虎',
      age: 18,
      hobby: ['唱', '跳', 'rap']
    }
    
    </script>
    
    <style scoped>
    
    </style>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    YaHooTest.vue

    <template>
      <div>你好,邵雅虎</div>
      <div v-if="showPerson" style="backgroundColor:black;color:white">
        <h3>人物信息卡</h3>
        <h5>姓名:{{ person.name }}</h5>
        <h5>年龄:{{ person.age }}</h5>
        <h5>爱好:<span v-for="(item, index) in person.hobby" :key="index">{{ item }}</span></h5>
        <button @click="closePerson">关闭</button>
      </div>
      输入框:<input type="text" v-model="txt">
    </template>
    
    <script setup lang="ts">
    import { ref, PropType } from 'vue'
    export interface Person {
      name: String,
      age: Number,
      hobby: Array<String>
    }
    let txt = ref('')
    let showPerson = ref(false)
    // 打开人物信息卡
    const openPerson = () => {
      showPerson.value = true
    }
    // 关闭人物信息卡
    const closePerson = () => {
      showPerson.value = false
    }
    defineExpose({
      txt,
      openPerson
    })
    defineProps({
      person: Object as PropType<Person>
    })
    </script>
    
    <style scoped>
    
    </style>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42

    在这里插入图片描述

    这样一来我们的值就从父组件传递到子组件当中去了,其中,我们用到了 ts 的泛型和类型断言

    在这里插入图片描述

    可以看到,显示效果和之前写死是一样的

    defineEmits

    那么接下来,我们就来写组件的自定义事件,组件向外暴露的方法

    我们写一个当输入框的内容为 hello shaoyahu 的时候就弹出一个窗口的事件,当然了,为了好看一些,我决定将弹出事件延迟100毫秒

    我们使用监听器来判断输入框的内容是否是我们想要的值

    App.vue

    <template>
      <h1>hello 邵雅虎</h1>
      <hr>
      <ya-hoo-test ref="testRef" :person="p" @say="fn"></ya-hoo-test>
      <br>
      <button @click="conInput">打印输入框的内容顺便打开人物信息卡</button>
      <h3>当输入框的内容为 hello shaoyahu 时会暴富</h3>
    </template>
    
    <script setup lang="ts">
    import { ref } from 'vue'
    import YaHooTest, { Person } from './components/YaHooTest.vue';
    
    const testRef = ref(null)
    const conInput = () => {
      console.log(testRef.value.txt)
      testRef.value.openPerson()
    }
    let p: Person = {
      name: '邵雅虎',
      age: 18,
      hobby: ['唱', '跳', 'rap']
    }
    const fn = () => {
      alert('借你吉言!')
    }
    </script>
    
    <style scoped>
    
    </style>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    YaHooTest.vue

    <template>
      <div>你好,邵雅虎</div>
      <div v-if="showPerson" style="backgroundColor:black;color:white">
        <h3>人物信息卡</h3>
        <h5>姓名:{{ person.name }}</h5>
        <h5>年龄:{{ person.age }}</h5>
        <h5>爱好:<span v-for="(item, index) in person.hobby" :key="index">{{ item }}</span></h5>
        <button @click="closePerson">关闭</button>
      </div>
      输入框:<input type="text" v-model="txt">
    </template>
    
    <script setup lang="ts">
    import { ref, PropType, watch } from 'vue'
    export interface Person {
      name: String,
      age: Number,
      hobby: Array<String>
    }
    let txt = ref('')
    let showPerson = ref(false)
    // 打开人物信息卡
    const openPerson = () => {
      showPerson.value = true
    }
    // 关闭人物信息卡
    const closePerson = () => {
      showPerson.value = false
    }
    // 监听输入框的值
    watch(txt, (newV, oldV) => {
      if (newV.toString() == 'hello shaoyahu') {
        setTimeout(() => {
          emit('say')
        }, 100);
      }
    })
    defineExpose({
      txt,
      openPerson
    })
    defineProps({
      person: Object as PropType<Person>
    })
    const emit = defineEmits(['say'])
    </script>
    
    <style scoped>
    
    </style>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51

    在这里插入图片描述
    OK ,那么效果就是这样一个效果了,我们成功的触发了我们的自定义事件

    结束

    这篇文章的内容确实也比较少,但是只要是写过 vue2 组件的朋友只需要看看这几个新的写法就可以上手了,毕竟其他的东西和 vue2 时期相差不大,当然了,我觉得相差不大也可能是因为我比较菜,谢谢你的观看希望都能有所收获

    文件链接

    同样的,这个练习的链接我也放在这里,和之前一样,都是免费的,毕竟也没啥值钱的东西嘛

    https://download.csdn.net/download/shaoyahu/87035327

  • 相关阅读:
    【pandas小技巧】--列值的映射
    免杀Veil-catapult
    使用阿里PAI DSW部署Stable Diffusion WebUI
    pychon假消息生产器
    Redis数据类型(list\set\zset)
    游戏道具平台|基于Springboot+Vue实现游戏道具平台系统
    上海物理、化学高考命题趋势及2024年上海物理、化学高考备考建议
    ChatGLM系列五:Lora微调
    自动化测试中的失败截图和存log
    将组件直接绑定到vue实例上面的写法
  • 原文地址:https://blog.csdn.net/shaoyahu/article/details/127886633