vue3中jsx使用的特殊地方

归纳总结一下vue3中使用jsx特殊的地方,就不对jsx的基本语法做介绍了

jsx在vue中意味着什么

jsx元素在vue中相当于一个render函数,也就是说

ts 复制代码
const Btn = <button onClick={() => count.value++}>click{count.value}</button>

相当于

ts 复制代码
const Btn2 = h('button', {
 onClick: () => count.value++,
}, `click${count.value}`)

关于vue和react的render

仅针对于现在vue的setup写法和react hooks的写法

vue 的组件可以分成setup阶段和render阶段,而react相当于只有render阶段,两者在数据变更从而视图需要更新时所做的事情其实是类似的,都是重新执行render函数,创建新的vnode

在vue中

tsx 复制代码
export const Com = defineComponent({
  setup: () => {
    const count = ref(1)

    const interval = setInterval(() => {
      count.value++
    }, 1000)

    onBeforeUnmount(() => {
      clearInterval(interval)
    })

    return {
      count,
    }
  },
  render: (props: any) => {
    console.log('render')// 每次render都会执行
    return <p>{props.count}</p>
  },
})

在react中

tsx 复制代码
function App() {
  const [count, setCount] = useState(0)

  useEffect(() => {
    const interval = setInterval(() => {
      setCount(count + 1)
    }, 1000)

    return () => clearInterval(interval)
  })

  console.log('render')// 每次render都会执行

  return (
    <p>{count}</p>
  )
}

react中每次执行函数得到一个新的VNode,并通过hooks来保证同一个组件前后数据的一致和一些副作用的设置和清除。而vue中同样是每次执行render函数得到一个新的VNode,不同的是,vue的数据和副作用的设置是放在setup阶段的,仅会执行一次。

因此,在vue的render函数中,不要编写含有副作用的代码,这大概率会引发bug,因为vue并没有提供react hooks类似的api去做一些副作用的设置和清除。

使用jsx编写函数式组件

使用jsx最常用的场景就是编写函数式组件,基本写法是这样的

tsx 复制代码
const Com = () => <button>click</button>

相当于一个只有render函数的组件,它的数据和副作用都从外部来,自身只负责创建VNode渲染

函数式组件的入参

除了可以使用上下文的数据进行渲染外,函数式组件还可以接受入参,它的参数是这样的

tsx 复制代码
export const FuncCom = (props: any, { attrs, slots, emit }: any) => <div>{{ ...slots }}</div>

这里的props和attrs是一样的,emit也就是vue的emit,slots也就是vue的slots

结合ts编写函数式组件

通过给props添加类型声明,可以给函数式组件更好的类型提示,例如

tsx 复制代码
export const FuncCom = (props: {
 value: string
 'onUpdate:value'?: (val: string) => void
 [key: string]: unknown
}) =>
 (<input type="text" value={props.value} onChange={(e) => {
   props['onUpdate:value']?.((e.target as any).value)
 }}/>)

使用方式

html 复制代码
<FuncCom v-model:value="value" />

对于普通的props类型都可以通过 value:string 这样的类型添加在props里面;

对于事件类型,vue3可以通过将对应事件改成on开头的props达到类型提示,如

tsx 复制代码
export const FuncCom = (props: {
  onEvent?: (e: Event) => void
  [key: string]: unknown
}) => <></>

这样就生成了一个event的事件类型提示,既可以传递onEvent,也可以传递@event,看起来就跟正常的组件一样

例子里使用 props['onUpdate:value']?.((e.target as any).value) 去传递事件,这在大多数情况下是可行的,但如果你给函数式组件添加了多个事件监听器,则还是建议采用emit的形式发送事件

对于slots类型,没找到方法

至于为什么需要加上

ts 复制代码
[key: string]: unknown

则是因为函数式可能需要传递一些组件通用可传递的属性,例如class,style,title等,免得传递这些属性时报类型错误

需要提醒的是,props仅限于类型声明,它不是真正的props

例如组件声明一个props为showTitle,则在template中,我们不论写showTitle还是show-title都是可行的,因为vue会对其进行处理

但是对于函数式组件声明的showTitle,则只能传递showTitle,而不能是show-title

tsx 复制代码
export const FuncCom = (props: {
 showTitle: string
}) => <span>{props.showTitle}</span>
html 复制代码
<FuncCom show-title="666" /> // 无效的
<FuncCom showTitle="666" /> //有效的

以上

相关推荐
源码获取_wx:Fegn089513 分钟前
计算机毕业设计|基于springboot + vue景区管理系统(源码+数据库+文档)
java·vue.js·spring boot·后端·课程设计
徐小夕@趣谈前端1 小时前
NO-CRM 2.0正式上线,Vue3+Echarts+NestJS实现的全栈CRM系统,用AI重新定义和实现客户管理系统
前端·javascript·人工智能·开源·编辑器·echarts
catino1 小时前
图片、文件上传
前端
Mr Xu_1 小时前
Vue3 + Element Plus 实现点击导航平滑滚动到页面指定位置
前端·javascript·vue.js
小王努力学编程2 小时前
LangChain——AI应用开发框架(核心组件1)
linux·服务器·前端·数据库·c++·人工智能·langchain
pas1362 小时前
35-mini-vue 实现组件更新功能
前端·javascript·vue.js
前端达人2 小时前
为什么聪明的工程师都在用TypeScript写AI辅助代码?
前端·javascript·人工智能·typescript·ecmascript
快乐点吧2 小时前
使用 data-属性和 CSS 属性选择器实现状态样式控制
前端·css
EndingCoder3 小时前
属性和参数装饰器
java·linux·前端·ubuntu·typescript
小二·3 小时前
Python Web 开发进阶实战:量子机器学习实验平台 —— 在 Flask + Vue 中集成 Qiskit 构建混合量子-经典 AI 应用
前端·人工智能·python