Vue3 JSX 语法速查:v-model、事件、插槽一网打尽

Vue3 JSX 以 JS 原生逻辑替代模板语法,核心转换规则如下:

  • 条件渲染 :v-if → &&/ 三元表达式;v-show 直接保留
  • 循环渲染 :v-for → 数组 map 遍历
  • 事件处理 :事件名驼峰化,修饰符用 withModifiers 包裹
  • 双向绑定 :v-model 支持基础、自定义名、修饰符及多 model 场景
  • 插槽:支持默认 / 具名 / 作用域插槽,渲染与传递写法清晰
typescript 复制代码
import { ref } from 'vue'
export default function add(props, ctx) {
    let visible = props.visible
    let form = props.form
    let plus = props.isPlus
    let addFormRef = ref()
    async function handleOk() {
        const error = await addFormRef.value.validate()
        if (error) return
        let url = plus ? 'insert' : 'update'
        let msg = plus ? '新增成功' : '更新成功'
        proxy.post(`/api/mapbus/pm/project/${url}`, form).then((res) => {
            proxy.$message.success(msg)
            ctx.emit('success')
        })
    }
    return (
        <a-drawer visible={visible} title={plus ? '新建' : '编辑'} width="30%" onOk={handleOk}>
            <a-form ref={addFormRef} model={props.form} auto-label-width>
                <a-form-item field="projectName" label="项目名称" validate-trigger="blur" rules={{required: true, message: '项目名称必填'}}>
                    <a-input v-model={form.projectName}></a-input>
                </a-form-item>
                <a-form-item field="remark" label="说明">
                    <a-input v-model={form.remark}></a-input>
                </a-form-item>
            </a-form>
        </a-drawer>
    )
}

一、常规逻辑

  • v-if: 转换成 js逻辑,三元表达式也可;
  • v-show: 支持;可直接写成v-show;
  • v-for:转换成js逻辑,forEach,map...等数组循环方式;
  • 事件:依驼峰命名方式写,onClick,onMouseOver...等等
  • js: 用花括号包起来;
  • 对象:用两个花括号,外围的括号是js的括号,里面括号才是对象的括号;

二、事件

  1. 事件以驼峰命名方式定义;

  2. 事件要是有修饰符的话:

  • 以常规驼峰命名写;
typescript 复制代码
<input
  onClickCapture={() => {}}
  onKeyupOnce={() => {}}
  onMouseoverOnceCapture={() => {}}
  />
  • 可以使用 withModifiers 函数
typescript 复制代码
<div onClick={withModifiers(() => {}, ['self'])} />

三、v-model

Vue3 jsx新特性,支持v-model使用

(一)、modelValue

如果组件的v-model是modelValue的话,那使用很简单;

typescript 复制代码
renderDropdown(h){
	const value = "value"
	return <custom-component v-mode={value}>
		code...
	</custom-component>
}

自定义value

比如v-model:visible=show写法如下:

typescript 复制代码
renderDropdown(h){
  const show = "true"
  return <el-popover v-model={[show, 'visible']}>
    code...
  </el-popover>
}

修饰符

  1. v-model后面跟着,使用(_)代替(.);vModel_trim = {value}
  2. withModifiers
typescript 复制代码
// template<input v-model="val" />
<input v-model:name="val">
<input v-model.trim="val">
<input v-model:name.trim="val">

// tsx
<input v-model={val} />
<input v-model={[val, 'name']} />
<input v-model={[val, ['trim']]} />
<input v-model={[val, 'name', ['trim']]} />

多个model

typescript 复制代码
// template
<A v-model="foo" v-model:bar="bar" />

// tsx
<A v-models={[[foo], [bar, "bar"]]} />

四、插槽

(一·)、渲染插槽

  1. js的方式
typescript 复制代码
// 默认插槽
<div>{slots.default()}</div>

// 具名插槽
<div>{slots.footer({ text: props.message })}</div>
  1. 以dom的形式
typescript 复制代码
export default function common(props, ctx) {
    const children = ctx.slots.default()[0]
    function handleBack() {
        ctx.emit('back', 12)
    }
    return (
        <div className={commonCss.panelContainer}>
            <div className={commonCss.header}>
                <MyIcon name="return" size={16} style={{cursor: 'pointer'}} onClick={handleBack}></MyIcon>
            </div>
            <children></children>
        </div>
    )
}

(二)、传递插槽

typescript 复制代码
// 默认插槽
<MyComponent>{() => 'hello'}</MyComponent>

// 具名插槽
<MyComponent>{{
  default: () => 'default slot',
  foo: () => <div>foo</div>,
  bar: () => [<span>one</span>, <span>two</span>]
}}</MyComponent>

也可以如下:

typescript 复制代码
// 具名插槽
<MyComponent v-slots={{
  default: () => 'default slot',
  foo: () => <div>foo</div>,
  bar: () => [<span>one</span>, <span>two</span>]
}}></MyComponent>

(四)、作用域插槽

typescript 复制代码
<MyComponent>{{
  default: ({ text }) => <p>{ text }</p>  
}}</MyComponent>

五、总结

模板语法(Template) JSX/TSX 语法 说明
v-if="show" {show && <div>内容</div>} 三元表达式也可:{show ? <div>显示</div> : <div>隐藏</div>}
v-show="show" <div v-show={show}>内容</div> 直接支持 v-show
v-for="item in list" {list.map(item => <div>{item}</div>)} 需加 key
@click.stop="handleClick" onClick={withModifiers(handleClick, ['stop'])} 修饰符用 withModifiers 包裹
v-model:visible="show" <el-popover v-model={show, 'visible'}>

感谢您抽出宝贵的时间观看本文;本文是 Vue3 核心 API 系列的第 2 篇,后续会持续更新 computed、ref/reactive、生命周期等实战内容,同时正在整理「Vue3 完整项目实战小册」(包含从 0 到 1 开发小程序 / 管理系统的全流程),欢迎关注~

相关推荐
u0111026753 小时前
JPG、PNG、WebP 怎么选?按透明度、体积和使用场景做判断
前端·javascript·vue.js·图像处理·ai作画
雪芽蓝域zzs8 小时前
第 7 节:多边形点击弹窗 + 清空绘制按钮
vue.js
溪语流沙8 小时前
【Web全栈进阶】Composition API与组件通信:props深入、emit、插槽
前端·css·vue.js
顽疲11 小时前
Java vue 养老系统源码详解:入住核算单 live-check 缴费入账与预交金收据实践
java·vue.js·python·java 养老·springboot 养老·vue养老
志尊宝12 小时前
Vue3 零基础每日笔记(088·完结):从零到一——一个完整 Vue3 项目的成长复盘
前端·javascript·vue.js·笔记·ecmascript·#vue.js
桔筐13 小时前
Vue中DOM的data-*自定义属性(dataset)与Vue data响应式变量区别详解
前端·javascript·vue.js
用户17335980753714 小时前
纯前端 PDF 按书签拆分避坑指南:拆分后章节对不上?
前端·javascript·vue.js
雪芽蓝域zzs15 小时前
Webstorm打开uniapp uvue文件报红处理方案
vue.js
撸串-研究生16 小时前
面向景区的综合服务管理平台设计——以稻城亚丁景区为例【附源码】
java·开发语言·vue.js·前后端分离·稻城亚丁景区
志尊宝1 天前
Vue3 零基础每日笔记(082):文件上传实战——el-upload 校验、自定义上传、头像预览
前端·javascript·vue.js·笔记·#javascript·#vue.js