一篇文章学会在vue3中使用jsx

jsx与template

无论是react还是vue,实质的生产环境打包产物(运行时)是不存在jsx或template文件的,它们在编译时会被处理成对应的render函数,作为种子在客户端渲染成页面。

jsx和template的存在都是为了开发者便捷编写视图代码(直接写render函数过于繁琐)。相比template,jsx有如下优点:

  1. JavaScript的表达能力: JSX 是 JavaScript 的扩展,因此你可以在 JSX 中使用 JavaScript 的所有功能。这意味着你可以在 JSX 中使用条件语句、循环、变量,以及其他 JavaScript 的高级特性。这种灵活性可以使得在 UI 描述中更容易实现复杂的逻辑。
  2. 更接近 JavaScript: 对于熟悉 JavaScript 的开发者来说,JSX 更接近他们的编程语言,因为它实际上就是 JavaScript 的语法扩展。这使得学习曲线相对较低,并且更容易理解。
  3. 组件内逻辑和渲染在一起: 在 JSX 中,组件的逻辑和渲染通常在同一个文件中,使得组件的代码更加紧凑和易于维护。
  4. 更强大的生态系统: React 生态系统是非常庞大且活跃的,JSX 作为 React 的一部分,受益于 React 生态系统的丰富资源和社区支持。

在vue3中使用jsx

创建组件

javascript 复制代码
import { defineComponent } from "vue";
export default defineComponent({
  setup() {
    return () => <div>Hello</div>;
  }
});

嵌入动态值

在jsx中使用动态值,在vue中我们使用双括号,这里使用单括号。

ps:如果使用ref必须加.value取值。

javascript 复制代码
//test.js
import { defineComponent, ref, reactive } from "vue";
export default defineComponent({
  props: ["text"],
  setup(props) {
    let num = ref(1);
    let article = reactive({ text: "hi" });
    return () => (
      <div>
        <div>{num.value}</div>
        <div>{article.text}</div>
        <div>{props.text}</div>
      </div>
    );
  }
});

//main.js
import { createApp, defineComponent } from "vue";
import test from "./components/test";
const App = defineComponent({
  setup() {
    return () => <test text={"你好"} />;
  }
});
createApp(App).mount("#app");

实现v-if v-for功能

你可以将jsx中的标签视作一定程度上的js类型数据,它可以参与三元运算,作为参数返回,作为数组的组成元素等。正因为如此,jsx不需要v-if指令实现视图条件展示,通过js条件语句直接进行判断返回对应视图渲染即可,通过工厂函数我们可以获得比template更好的代码可读性。

ps:在jsx中使用js运行语句需要使用大括号包裹。

javascript 复制代码
 setup() {
    function factory(id) {
      switch (id) {
        case 1:
          return <div>一</div>;
        case 2:
          return <div>二</div>;
      }
    }
    let ok = ref(false);
    return () => (
      <div>
        <div>{ok.value ? <div>yes</div> : <span>no</span>}</div>
        <div>{factory(2)}</div>
      </div>
    );
  }

当遇到jsx类型元素的数组时,会自动循环渲染到页面

javascript 复制代码
setup() {
    const arr = ref([<div>1</div>, <div>2</div>]);
    return () => <div>{arr.value}</div>;
  }

利用这个特性我们可以结合map函数这样做,这样就实现了v-for:

javascript 复制代码
  setup() {
    const arr = ref([
      { id: 1, name: "tsz" },
      { id: 2, name: "jsx" }
    ]);
    return () => (
      <div>
        {arr.value.map((e) => {
          return (
            <div>
              <span style="color:red">{e.id}</span>
              <span>{e.name}</span>
            </div>
          );
        })}
      </div>
    );
  }

实现v-bind v-on功能

属性绑定也是使用大括号包裹

javascript 复制代码
  setup() {
    const href = ref("https://www.bing.com/");
    return () => <a href={href.value}>DevUI Design</a>;
  }

以 on 开头,并跟着大写字母的 props 会被当作事件监听器。比如,onClick 与模板中的 @click 等价。

javascript 复制代码
  setup() {
    return () => (
      <button
        onClick={(event) => {
          /* ... */
        }}
      >
        click me
      </button>
    );
  }

事件修饰符设置

对于 .passive、.capture 和 .once 事件修饰符,使用驼峰写法将他们拼接在事件名后面:

ini 复制代码
  setup() {
    return () => (
     <input
 		 onClickCapture={() => {}}
 		 onKeyupOnce={() => {}}
 		 onMouseoverOnceCapture={() => {}}
			/>
    );
  }

实现插槽功能

javascript 复制代码
  setup(props, { slots }) {
    let inerdata=ref('来源')
    return () => (
      <div>
        <div>{slots.title?.()}</div>
        <div>{slots.default?.()}</div>
        <div>{slots.footer?.(inerdata.value)}</div>
      </div>
    );
  }

使用插槽相对比较麻烦,我这里推荐 传递一个配置对象 的方式

javascript 复制代码
import { createApp, defineComponent } from "vue";
import test from "./components/test";
const App = defineComponent({
  setup() {
    return () => (
      <test>
        <div>233</div>
      </test>
    );
  }
});
createApp(App).mount("#app");
javascript 复制代码
  setup() {
    return () => (
      <test>
        {{
          default: () => <div>水水水水水水水水水水水水水</div>,
          title: () => <h1>我的祖国</h1>,
          footer: (inerdata) => <h6>{inerdata}:来自网络</h6>
        }}
      </test>
    );
  }

v-model

jsx是支持v-model语法的,需要注意的是与事件绑定不同,指令的修饰符是可以像template加在其后

javascript 复制代码
// 正常写法
<input v-model="value" /> // vue
<input v-model={value} /> // jsx

// 指定绑定值写法
<input v-model:modelValue="value" /> // vue
<input v-model={[value,'modelValue']} /> // jsx

// 修饰符写法
<input v-model:modelValue.trim="value" /> // vue
<input v-model={[value,'modelValue',['trim']]} /> // jsx

扩展:在template中混杂 函数式组件

函数式组件是一种定义自身没有任何状态的组件的方式。它们很像纯函数:接收 props,返回 vnodes。函数式组件在渲染过程中不会创建组件实例 (也就是说,没有 this),也不会触发常规的组件生命周期钩子。

我们可以在模板(SFC)文件中定义后直接使用,在一些特定场景中比较实用。

xml 复制代码
<template>
  <MyComponent :value="23" @print="print" />
</template>

<script setup lang="jsx">
// import { ref } from 'vue';
function print(e){console.log(e);}
function MyComponent(props, { slots, emit, attrs }) {
    return (
      <div>
        <div>{props.value}</div>
        <button onClick={()=>{emit('print',233)}}/>
      </div>
    );
}
MyComponent.props = ['value']
MyComponent.emits = ['print']
</script>
相关推荐
昨天;明天。今天。1 小时前
案例-表白墙简单实现
前端·javascript·css
数云界1 小时前
如何在 DAX 中计算多个周期的移动平均线
java·服务器·前端
风清扬_jd1 小时前
Chromium 如何定义一个chrome.settingsPrivate接口给前端调用c++
前端·c++·chrome
安冬的码畜日常1 小时前
【玩转 JS 函数式编程_006】2.2 小试牛刀:用函数式编程(FP)实现事件只触发一次
开发语言·前端·javascript·函数式编程·tdd·fp·jasmine
ChinaDragonDreamer1 小时前
Vite:为什么选 Vite
前端
小御姐@stella1 小时前
Vue 之组件插槽Slot用法(组件间通信一种方式)
前端·javascript·vue.js
GISer_Jing1 小时前
【React】增量传输与渲染
前端·javascript·面试
GISer_Jing1 小时前
WebGL在低配置电脑的应用
javascript
eHackyd1 小时前
前端知识汇总(持续更新)
前端
万叶学编程5 小时前
Day02-JavaScript-Vue
前端·javascript·vue.js