template模板语法

ads

前言

点击上方 熊的猫 本公众号会定期分享技术干货,也可快速加入前端交流群!


大多数 Vue 开发者都习惯使用 template 模板语法,因为 template 模板语法 具有如下优点:

  • 熟悉的类 HTML 结构

    • 模板语法可以像 HTML 一样进行布局和设计,上手快、学习成本比低

  • 更简洁的写法

    • 例如,可以在模板中使用各种 修饰符 来达到简化编写代码的过程

  • 结构与逻辑分离

    • 元素结构和逻辑并没有杂糅在一起,因此结构上更简洁明了

  • 提供更好的性能

    • Vue3 中对模板语法在 编译阶段 进行的各种优化,使得其性能更好

但即便如此,在某些场景下还是不得不在 Vue 中使用 jsx 语法 实现需求, 例如开发 内部组件库 选择的编写形式就是 jsx 语法 等。

而对于习惯使用 template 模板语法 的开发者并不是轻易的就能转换到相应 jsx 语法,因此本文就列举一些 template 模板语法 中对应的 jsx 语法 应该怎么写。

从 template 到 jsx

插值表达式(文本插值)

template 语法

最基本的数据绑定形式就是 文本插值,它使用的是 Mustache 语法 (即 {{}} ),双大括号 中的内容最终 会将数据解释为纯文本

<span>Message: {{ msg }}</span>

jsx 语法

而 JSX 中使用 文本插值 就从 双大括号 {{ }} 变成 单大括号 {}

<span>Message: { msg }</span>

原始 HTML

template 语法

双大括号 会将数据解释为纯文本,而不是 HTML,因此若想在模板中 插入 HTML,我们需要使用 v-html 指令

// html 字符内容rawHtml = '<span>hello!</span>'
// 最终变成纯文本<p>Using text interpolation: {{ rawHtml }}</p>
// 最终渲染为 html 结构<div>Using v-html directive: <p v-html="rawHtml"></p></div>

jsx 语法

而在 jsx 语法 中就更直接了,我们直接通过 变量 的形式来写 html 结构 配合上 文本插值 {} 即可:

// 最终变成纯文本cosnt rawHtml = '<span>hello!</span>'<p>Using text interpolation: { rawHtml }</p>
// 最终渲染为 html 结构cosnt rawHtml = <span>hello!</span><div>Using v-html directive: { rawHtml }</div>

条件渲染

template 语法

在模板语法中和 条件渲染 相关的可以直接使用指令 v-if / v-show 来实现:

<p v-show="isShow">hello world!</p><p v-show="!isShow">hello bros!</p>
<p v-if="isShow">hello world!</p><p v-else>hello bros!</p>

jsx 语法

而在 jsx 语法 中我们就不能使用 指令形式 了,取而代之的是 JavaScript 中的 if-else、&&、||、三元表达式 等形式:

if-else

const content = (isShow) => {    if(isShow){      return <h1>hello world!</h1>    }else{      return <div>hello bros!</div>    }}

&&

{ isShow && <div>hello world!</div> }{ !isShow && <div>hello bros!</div> }

||

const content1 = <h1>hello world!</h1>const content2 = <h1>hello world!</h1>
<div>{ content1 || content2 } </div>

三元表达式

const content1 = <h1>hello world!</h1>const content2 = <h1>hello world!</h1>
<div>{ isShow ? content1 : content2 } </div>

列表渲染

tempalte 语法

在 template 模板 中可以通过 v-for 指令 来快速实现列表渲染:

<ul>  <li v-for="item in list" :key="item.key">{{ item.text }}</li></ul>

jsx 语法

在 jsx 语法 中通常是使用 Array.prototype.map() 方法来实现列表渲染,原因就在于这个遍历数组的方法返回值也是数组:

<ul>  {    list.map((item) => (      <li key={item.key}>{ item.text }</li>    ))  }</ul>

style 外部样式

template 语法

在 .vue 文件 中可以通过 <style> 标签来 编写样式 或 导入外部样式,还可以直接通过设置 scope 实现局部样式:

<script setup lang="ts">import { ref } from "vue";import ChcekBox from "./components/CheckBox";
const checkResult = ref(false);</script>
<template> <ChcekBox v-model="checkResult">选项</ChcekBox></template>
<style scope>@import './index.less';</style>

jsx 语法

而在一个 .jsx / .tsx 文件中由于不存在 <style> 元素,因此无法通过其来编写或导入样式,或者通过 scope 实现局部样式,可通过如下方式导入:

  • 直接 import 导入

    import { defineComponent, ref } from 'vue'import './index.less'
    export default defineComponent({})
  • 通过 CSS Module 导入

    import { defineComponent, ref } from 'vue'import styleModule from './index.module.less'
    export default defineComponent({ setup() { return () => ( <label class={styleModule.abs}>hello world!</label> )})

事件绑定

tempalte 语法

在模板语法中绑定事件可以使用 v-on(简写 @) 来实现,并且可以在模板中 直接传递参数 给目标事件,也可以配合使用 事件修饰符,支持内联事件等等。


绑定处理函数

<!-- 方法处理函数 --> <button v-on:click="doThis"></button>
<!-- 缩写 --> <button @click="doThis"></button>

使用修饰符

<!-- 链式调用修饰符 --><button @click.stop.prevent="doThis"></button>

传递参数

<!-- 传参 --> <button @click="doThis($event, params)"></button>

内联事件

<!-- 传参 --> <button @click="count++"></button>

jsx 语法

上述写法在 jsx 语法 中的对应写法具体如下:

绑定处理函数

需要使用 on + [eventName] 的形式来绑定事件,可使用 或 不使用 驼峰形式,但当使用 typescript 时建议使驼峰形式,否则会有提示:

<!-- 驼峰 --> <button onClick={doThis}></button>
<!-- 非驼峰 --> <button onclick={doThis}></button>

使用修饰符

在 jsx 语法 中不能直接使用 .stop 形式的事件修饰符,需要通过 withModifiers 函数来实现,其支持 事件和按键修饰符

<!-- withModifiers  --><button onClick={withModifiers(doThis, ['prevent'])}></button>
传递参数

在 jsx 语法 中不能像在模板中使用 handleAction($event, params) 的方式来实现传参,因为这种写法在 jsx 中属于调用,因此相当于把函数返回值作为事件绑定到目标元素上,大多数情况下会抛出异常(即返回值不一定为函数):

  • 使用 bind 实现传参

    const bindEvent = doThis.bind(tarrget)
    <!-- 传参 --><button onClick={bindEvent}></button>
  • 使用 箭头函数 实现传参

    <!-- 传参 --><button onClick={ (parms) => bindEvent(parms)}></button>
内联事件

在 jsx 语法 并不支持内联事件的写法,因此可以使用箭头函数来包裹:

<!-- 方式一 --><button onClick={ () => count++ }></button>
<!-- 方式一 -->const addCount = () => count++<button onClick={ addCount }></button>

双向绑定 v-model

template 语法

v-model 可以在组件上使用以实现 双向绑定

  • 在 原生表单元素 上使用 v-model 会被编译为 value 属性 和 input 事件

  • 在 组件 上使用 v-model 会被编译为 modelValue 属性 和 update:modelValue 事件

  • 支持自定义 v-model 绑定的 属性名 和 事件名

// 常见表单<input v-model="searchText" />
// 自定义组件<CustomInput v-model="searchText" />
// 自定义 v-model 名<MyComponent v-model:title="bookTitle" />

jsx 语法

正常绑定

<CustomInput v-model={searchText} />
自定义名称

jsx 语法 中不存在类似 v-model:title 的命名形式,因此我们给 v-model 一个数组,如 [title, 'titleAlias']

  • 数组的第一个参数就是要绑定的 

  • 数组的第二个参数就是要绑定的 自定义名称

<Custom v-model={[title, 'titleAlias']} />

slot 插槽

template 语法

在模板语法中可以 <slot> 元素来定义 插槽出口,用于标示父元素提供的 插槽内容 的渲染位置:

默认插槽

<button class="fancy-btn">  <slot></slot> <!-- 插槽出口 --></button>
具名插槽
<button class="fancy-btn">  <slot name="content"></slot> <!-- 插槽出口 --></button>
动态插槽
<div>     <!-- 动态插槽 -->     <template v-slot:[dynamicSlotName]> ... </template> 
<!-- 缩写为 --> <template #[dynamicSlotName]> ... </template> </base-layout></div> 
作用域插槽
<!-- MyComponent 模板 --> <div>    <slot :text="greetingMessage" :count="1"></slot> </div>
<!-- 父组件模板 --> <MyComponent v-slot="slotProps"> {{ slotProps.text }} {{ slotProps.count }} </MyComponent>

jsx 语法

由于 jsx 语法 中不存在 <slot> 元素,因此只能通过如下方式来渲染插槽内容:

  • 从 SetupContext 中获取

    defineComponent({    setup(props, { slots }) {        return <div>            { slots.default && slots.default() }            { slots.nameSlot && slots.nameSlot() }        </div>    }})
  • 使用 useSlot() 方法

    import { defineComponent, renderSlots } from 'vue'
    defineComponent({ setup(props, context) { const slots = useSlots(); return <div> { renderSlot(slots, 'default') } </div> }})
  • 使用 renderSlot() 方法

    import { defineComponent, renderSlot } from 'vue'
    defineComponent({ setup(props, { slots }) { return <div> { renderSlot(slots, 'default') } </div> }})
  • 使用 Scoped Slots 作用域插槽

    <!-- MyComponent 模板 --> defineComponent({    setup(props, { slots }) {        const slotParams = { name: 'hello' };                return <div>            { slots.default && slots.default(slotParams) }        </div>    }})
    <!-- 父组件模板 -->defineComponent({ setup(props, { slots }) { return <div> <MyComponent v-slot="slotProps"> {{ slotProps.name }} </MyComponent> </div> }})

最后

点击下方 熊的猫 本公众号会定期分享技术干货,也可快速加入前端交流群!

以上就是本文的全部内容了,由于前段时间开始写 jsx 语法,期间总是需要来回查找对应的正确写法,于是就打算整理成文章顺便分享出来.

希望本文对你有所帮助!!!


最后编辑于:2024/1/9 拔丝英语网

admin-avatar

英语作文代写、国外视频下载

高质量学习资料分享

admin@buzzrecipe.com