React&Vue 系列:简述 Vue 中 的 JSX

08_logo.png

背景:作为使用三年 react.js 的搬运工,目前正在积极学习 vue.js 语法,而在学习的过程中,总是喜欢和 react.js 进行对比,这里也不是说谁好谁坏,而是怀有他有我也有,他没我还有的思想去学习,去总结。

  • React18
  • Vue3

最近看 vue 官网的时候,发现了 vue 中也使用 JSX/TSX,就比较的感兴趣。为什么呢?

因为在工作的三年过程中,都是使用的 React 进行开发的,而 React 就是使用的 JSX 语法进行开发的,对其基本语法也是比较熟悉的。若以后机会使用 vue 开发,那么 JSX 也不失为一种选择。

我记得最开始的,react jsx 的语法写习惯了,当写 vue 代码时,总会犯一个错误: {}{{}} 的写法。

vue 要使用 {{}}, react 要使用 {},不停的转变,最后造成的原因就是 react 那边喜欢写错,vue 这边也喜欢写错。 幸好的是,最近慢慢熟悉过来了

这里 react 中使用 JSX 使用语法就不用多做介绍了,写过 react 进行开发的码友都应该熟悉。

  • map 进行循环
  • 三目运算 或者 逻辑运算 进行判断
  • className 代替 class
  • 事件前面加上 on,采用驼峰式命名
  • 变量使用 {} 包裹

常用的就这些,直接开始 Vue 中的 JSX 旅程吧。

Vue 系列:JSX

先来个简单的介绍吧(我也不知道是哪里抄的,哈哈哈)

JSX(JavaScript XML)是一种用于在 javaScript 中编写类似 XML 的语法扩展。

JSX 允许开发者在 JavaScript 代码中直接编写类似 HTML 的标记语法,以声明式地描述 UI 组件的结构和交互。通过使用 JSX,可以将 HTML 结构、组件逻辑和数据绑定等内容组合在一起,更加直观地描述页面结构和交互。

安装插件并使用

create-vue 和 Vue Cli 都有预置的 JSX 语法支持,但是 vite 创建的项目是需要安装插件的

虽然下面说的都是 JSX, 但是创建的项目是 ts,都是采用 tsx 的书写方式。

使用 vue + vite 创建的项目是不支持 JSX,需要安装一个插件@vitejs/plugin-vue-JSX

pnpm add @vitejs/plugin-vue-JSX -D
// vite.config.ts
import { defineConfig } from "vite";
import vue from "@vitejs/plugin-vue";
import vueJSX from "@vitejs/plugin-vue-JSX";
​
// https://vitejs.dev/config/
export default defineConfig({
  plugins: [vue(), vueJSX()],
});

这样配置之后,就可以在项目中,使用 JSX 语法了。

使用 JSX 的两种方式

使用 JSX 文件存在两种形式,但都是使用 setup 函数的返回值来实现的。请确保返回的是一个函数而不是一个值!setup() 函数在每个组件中只会被调用一次,而返回的渲染函数将会被调用多次。

第一种方式: 采用.vue 文件后缀名。

  1. 修改 script 标签上的 lang 属性,从 ts 改为 tsx。
  2. setup 函数返回一个 render 函数,该函数的返回值是 JSX 语法
<script lang="tsx">
import { defineComponent, ref } from "vue";
​
export default defineComponent({
  setup() {
    const msg = ref("copyer");
    return () => (
      <div>{msg.value}</div>
    );
  },
});
</script>

第二种方式:采用 .tsx 文件后缀名

也是采用的 setup 返回 render 函数,该函数的返回值是 JSX 语法

import { defineComponent, ref } from "vue";
​
export default defineComponent({
  setup() {
    const msg = ref("copyer");
    return () => <div>{msg.value}</div>;
  },
});

具体采用哪种形式,就自己爱好了(其实 JSX 写法,本来在 vue 中很少使用)。

JSX VS template

template:

  • 更加贴近实际的 html。
  • 由于其确定的语法,更容易对模板做静态分析。这使得 Vue 的模板编译器能够应用许多编译时优化来提升虚拟 DOM 的性能表现。

JSX:

  • 处理高度动态渲染逻辑的可重用组件中使用。

JSX 的具体细节

官网已经明确的指出了,Vue 的 JSX 转换方式与 React 中 JSX 的转换方式不同,所以 JSX 的写法肯定会存在差异。

jsx 写法形式

选项语法

export default defineComponent({
  name: "test",
  props: {
    name: {
      type: String,
      required: true,
    },
  },
  // 拿取 props context: {emit, expose, slots, attrs }
  setup(props, context) {
    return () => {
      return <div>{props.name}</div>;
    };
  },
});

函数语法(vue3.3+)

import { defineComponent, ref } from "vue";
interface Props {
  name: string;
}
const TestTsx = defineComponent<Props>(
  (props, context) => {
    const msg = ref<string>("copyer");
    return () => (
      <div>
        <div>{msg.value}</div>
      </div>
    );
  },
  {
    // 需要手动声明运行时的 props,不然拿不到 props
    props: ["name"],
  }
);
export default TestTsx;

不能使用 className,而是直接使用 class

setup() {
    const msg = ref("copyer");
    return () => {
      return <div class="red">{msg.value}</div>;
    };
  },

动态 class 和 style

setup() {
  const show = ref(false);
  return () => (
    <div class="content">
      <div class={{ color: show.value }}>321321</div>
    </div>
  );
},

style 也是一样。

这种形式跟 react 采用 classnames 库的写法一致。

jsx 里面不能自动解包

就是针对 ref 变量,需要 .value,在上面案例即可验证。

组件插槽使用

在 jsx 中使用插槽,都是以函数的形式调用

const testslot = defineComponent({
  setup(props, { slots }) {
    return () => (
      <div>
        {/*默认插槽*/}
        <div>{slots.default && slots.default()}</div>
        {/*具名插槽*/}
        <div>{slots.footer && slots.footer()}</div>
      </div>
    );
  },
});

组件插槽传递

setup(props, context) {
  return () => {
    return (
      <div>
        <TestJsxVue
          v-slots={{
            default: () => <span>我是默认插槽</span>,
            footer: () => <span>我是具名插槽</span>,
          }}
        />
      </div>
    );
  };
},

这里的案例跟上面是对应的

注意:这里是使用的 v-slots 而不是 v-slot

作用域插槽就不用多说了,函数传递参数和函数接受参数。

事件修饰符

对于 .passive.capture.once 事件修饰符,可以使用驼峰写法将他们拼接在事件名后面(on+事件名+修饰符)。例如:

setup(props, context) {
  const btn = () => {
    console.log("321======>", 321);
  };
  return () => {
    return (
      <div>
        {/* 这里功能是好的,但是会飘红,不存在属性 onClickOnce */}
        <button onClickOnce={btn}>点击</button>
      </div>
    );
  };
},

对于事件和按键修饰符,可以使用 withModifiers 函数,vue 内部提供的。

支持部分的指令

  • v-text
  • v-html
  • v-show
 setup(props, context) {
  const text = ref("copyer");
  const show = ref(true);
  const btn = () => {
    console.log(321);
  };
  return () => {
    return (
      <div>
        {props.name}
        <button
          onClickOnce={btn}
          v-text={text.value}
          v-show={show.value}
        ></button>
      </div>
    );
  };
},

v-model 在组件上的使用

v-model 在组件上使用,默认名称就是 modelValue,也可以自定义名称,采用 v-model:title="xxx" 的方式。

默认值

<!-- 定义 -->
<script lang="tsx">
import { defineComponent, ref } from "vue";

export default defineComponent({
  props: {
    {/* v-model 的默认值 */}
    modelValue: {
      type: String,
    },
  },
  emits: ["update:modelValue"],
  setup(props, { emit }) {
    const btn = () => {
      emit("update:modelValue", "321");
    };
    return () => (
      <div>
        <button onClick={btn}>{props.modelValue}</button>
      </div>
    );
  },
});
</script>
// 组件中使用
export default defineComponent({
  setup() {
    const text = ref("copyer");
    return () => {
      return (
        <div>
          <TestJsxVue v-model={text.value} />
        </div>
      );
    };
  },
});

取名为 title

<!-- 定义 -->
<script lang="tsx">
import { defineComponent, ref } from "vue";

export default defineComponent({
  props: {
    {/* v-model 的取名 */}
    title: {
      type: String,
    },
  },
  emits: ["update:title"],
  setup(props, { emit }) {
    const btn = () => {
      emit("update:title", "321");
    };
    return () => (
      <div>
        <button onClick={btn}>{props.title}</button>
      </div>
    );
  },
});
</script>
// 使用
export default defineComponent({
  setup() {
    const text = ref("copyer");
    return () => {
      return (
        <div>
          {/* 取名为 title,是一个数组,[绑定的值,名称] */}
          <TestJsxVue v-model={[text.value, 'title']} />
        </div>
      )
    }
  }
})

存在其他的新 jsx 语法,以后慢慢收集。

总结

习惯 react 的 jsx 语法, 在 vue 写 jsx 应该也不在话下,当然 vue 还有一些个性的 jsx 语法,就需要在开发中平时积累。

上面存在错误的话,告诉我一下,因为 vue 我也不太会,我改正。

全部评论

相关推荐

点赞 收藏 评论
分享
牛客网
牛客企业服务