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

以上

相关推荐
猿饵块31 分钟前
cmake--get_filename_component
java·前端·c++
大表哥642 分钟前
在react中 使用redux
前端·react.js·前端框架
十月ooOO1 小时前
【解决】chrome 谷歌浏览器,鼠标点击任何区域都是 Input 输入框的状态,能看到输入的光标
前端·chrome·计算机外设
qq_339191141 小时前
spring boot admin集成,springboot2.x集成监控
java·前端·spring boot
pan_junbiao1 小时前
Vue使用代理方式解决跨域问题
前端·javascript·vue.js
明天…ling1 小时前
Web前端开发
前端·css·网络·前端框架·html·web
ROCKY_8171 小时前
web前端-HTML常用标签-综合案例
前端·html
海石1 小时前
从0到1搭建一个属于自己的工作流站点——羽翼渐丰(bpmn-js、Next.js)
前端·javascript·源码
Q186000000001 小时前
在HTML中添加图片
前端·html
傻虎贼头贼脑2 小时前
day21JS-npm中的部分插件使用方法
前端·npm·node.js