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" /> //有效的

以上

相关推荐
秦jh_8 分钟前
【Linux】多线程(概念,控制)
linux·运维·前端
蜗牛快跑21321 分钟前
面向对象编程 vs 函数式编程
前端·函数式编程·面向对象编程
Dread_lxy22 分钟前
vue 依赖注入(Provide、Inject )和混入(mixins)
前端·javascript·vue.js
涔溪1 小时前
Ecmascript(ES)标准
前端·elasticsearch·ecmascript
榴莲千丞1 小时前
第8章利用CSS制作导航菜单
前端·css
奔跑草-1 小时前
【前端】深入浅出 - TypeScript 的详细讲解
前端·javascript·react.js·typescript
羡与2 小时前
echarts-gl 3D柱状图配置
前端·javascript·echarts
guokanglun2 小时前
CSS样式实现3D效果
前端·css·3d
咔咔库奇2 小时前
ES6进阶知识一
前端·ecmascript·es6
渗透测试老鸟-九青2 小时前
通过投毒Bingbot索引挖掘必应中的存储型XSS
服务器·前端·javascript·安全·web安全·缓存·xss