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

写在前面

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

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

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

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

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

defineProps => 组件可以传入的值

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

开始

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

npm create vite

如下图选择就可以完成创建,再根据提示 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>

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>

在这里插入图片描述
在这里插入图片描述
这个文字内容完全是属于组件的一部分,和父组件是一点关系都没有,但是通过 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>

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>

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

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>

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>

在这里插入图片描述

这样一来我们的值就从父组件传递到子组件当中去了,其中,我们用到了 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>

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>

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

结束

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

文件链接

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

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

Logo

前往低代码交流专区

更多推荐