前言: 好记性不如烂笔头
pnpm sit:dev 18.18.0以上 components.ts export导出
在 Vue 3中,有两种声明组件的方式
常用的Template方式
TSX (TypeScript + JSX) ,tsx是一种声明组件的灵活方式,适合复杂逻辑场景中
优点:
- 类型支持与代码提示:TSX 能够利用 TypeScript 的类型推断功能,减少开发中的类型错误。
- 易于集成第三方库:TSX 更符合主流 JavaScript 库(例如 React)的写法。
- TSX 允许更好地利用 JavaScript 的功能来创建可组合的组件。
- 表达能力更加强,对于一些重复性的代码可抽取出来
缺点:
- 对于不熟悉 TypeScript 或 JSX 的开发者来说,TSX 可能需要一定的学习时间。
- 对于简单的模板,TSX 可能显得冗长且不如 Vue 的单文件组件(SFC)直观,尤其是在处理大量 HTML 时。
- 虽然 Vue 3 支持 TSX,但 Vue 社区和生态系统的许多工具和库仍然主要围绕 SFC 开发,因此在使用 TSX 时可能会遇到一些兼容性问题。
基础用法:
安装依赖 npm install @vitejs/plugin-vue-jsx -D
import vue from '@vitejs/plugin-vue';
import vueJsx from '@vitejs/plugin-vue-jsx'
export default {
plugins: [vue(), vueJsx()]
}
支持v-model的写法,但是值需要用花括号包裹起来
<ElInput placeholder="请输入收货人姓名" v-model={formData.value.name} />
支持v-show 不支持v-if,大多数情况下需使用三元运算符判断展示
let flag = ref(false)
const caseFn = () => {
return (
<div>
<div v-show={flag.value}>显示</div>
<div v-show={!flag.value}>隐藏</div>
</div>
)
}
const caseFn = () => {
return (
<div>
{
flag.value ? <div>显示</div> : <div>隐藏</div>
}
</div>
)
}
在templete下使用v-for来循环页面,在jsx中需要使用list.map方法处理循环数据
注意点: 循环处理数据时如果是动态切换的需要return 出去,否则页面不显示
let arr = [1,2,3,4,5]
const caseFn = () => {
return (
<div>
{
arr.map(v=>{
return <div>{v}</div>
})
}
</div>
)
}
v-bind使用 {...item} ,这样可以将 props 对象中的所有属性绑定到 <div> 元素上。className={item.className} 绑定单个元素, 在子组件中使用props接受参数
let arr = [1,2,3,4,5]
const caseFn = () => {
return (
<div>
{
arr.map(item => {
return (<li className={item} {...item}>{item}</li>)
})
}
</div>
)
}
事件处理
- 所有事件都为on开头,按react风格来
const caseFn = () => {
return (
<>
<button onClick={ clickTap }>点击</button>
</>
)
}
const clickTap = () => {
console.log('click');
}
样式
- 没有内置的
<style>支持,必须通过内联样式、CSS 模块或 CSS-in-JS 实现。 - 没有像 SFC 那样的
scoped样式支持,内联样式或 CSS 模块需要手动管理作用域。 - 默认不支持直接在 TSX 中嵌入
<style>标签。
import { defineComponent } from "vue"
import styles from "./styles.css"
export default defineComponent({
setup() {
return () => (
<div class={styles.container}>
<span class={styles.text}>Hello, Vue 3 TSX!</span>
</div>)
}
})
</style>
父子组件传值
父传子 onRefresh 接收子组件方法
<ShopOrder orderDetail={orderDetail.value} onRefresh={getData} />
子传父
props: {
orderDetail: {
type: Object as any
}
}
emits: {
close: (value: Boolean) => value, //抛出子组件方法
}
setup(props, { emit }) {
const goCloseDialog = () => {
emit('close', false)
}
}
插槽
定义子组件
import { defineComponent } from 'vue'
const Button = defineComponent({
setup(props, { slots }) {
return () => <button>{slots.default ? slots.default() : ''}</button>
}
});
export default Button
使用子组件
import { defineComponent } from 'vue'
import Button from './Button'
const App = defineComponent({
setup() {
return () => ( <Button> <span>Click Me!</span> </Button> )
}
})
export default App