Vue 3 第二十二章:组件十(组件高级特性-组件的渲染函数和JSX/TSX语法)

news/2024/11/8 9:39:09/

文章目录

  • 1. 渲染函数
  • 2. JSX / TSX 语法
    • 2.1. 基本使用
    • 2.2. 使用 vue 中的语法
      • 2.2.1. {} 语法
      • 2.2.2. v-model 使用
      • 2.2.3. v-show 使用
      • 2.2.4. v-if 不支持,实现v-if功能
      • 2.2.5. v-for 不支持,实现 v-for 功能
      • 2.2.6. v-bind 不支持,模拟 v-bind
      • 2.2.7. v-on 使用
      • 2.2.8. Props 使用
      • 2.2.9. Emit 使用
      • 2.2.10. v-slot 使用
  • 总结

1. 渲染函数

渲染函数是一种将组件的模板转换成虚拟 DOM 的方法。在 Vue 中,我们可以选择使用渲染函数来代替模板语法。

渲染函数可以让我们更加灵活地定义组件的模板,并且可以让我们在编写组件时使用JavaScript的全部语言特性。在Vue3中,我们可以使用 h 函数来创建虚拟 DOM 元素。h 函数接受三个参数:元素名元素的属性子元素

下面是一个简单的示例代码:

// ChildComponent.vue
<script lang="ts">
import { h } from "vue";export default {render() {return h("div", { class: "container", style: { color: "red" } }, [h("h1", "Hello, world!"),h("p", "h函数的基本使用"),]);},
};
</script>// Parent.vue
<template><div><child-component></child-component></div>
</template><script setup lang="ts">
import ChildComponent from "./ChildComponent.vue";
</script>

渲染到页面上的效果如下:
在这里插入图片描述

在上面的代码中,我们定义了一个渲染函数,并使用 h 函数来创建 div 元素、h1 元素和 p 元素。我们将这些元素作为子元素传递给 div 元素,并将 div 元素作为渲染函数的返回值。当我们在组件中使用渲染函数时,我们可以将其返回值渲染到页面上。

需要注意的是,在Vue3中,我们可以选择使用模板语法渲染函数来定义组件的模板。使用哪种方式取决于我们的个人喜好和项目的需求。

2. JSX / TSX 语法

JSX 是一种将XML语法嵌入到JavaScript中的语法。在 Vue3 中,我们可以使用JSX语法来编写组件的模板。使用JSX语法可以让我们更加灵活地定义组件的模板,并且可以让我们在编写组件时使用JavaScript的全部语言特性。

要在 Vue3 中使用 JSX 语法,我们需要安装 @vitejs/plugin-vue-jsx 插件,并在 vite.config.ts 文件中配置该插件。然后,我们就可以在组件中使用 JSX 语法了。

下面是一个简单的示例代码:

2.1. 基本使用

1)安装 @vitejs/plugin-vue-jsx

npm install @vitejs/plugin-vue-jsx -D

2)配置vite.config.ts
在这里插入图片描述
3)配置 tsconfig.json 文件
在这里插入图片描述

// vite.config.ts
import { fileURLToPath, URL } from "node:url";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()],resolve: {alias: {"@": fileURLToPath(new URL("./src", import.meta.url)),},},
});

3)使用TSX

// index.tsx
const tsxDom = () => {return (<><div class="container"><h1>Hello, world!</h1><p>This is a tsx.</p></div></>);
};export default tsxDom;
// tsx.vue
<template><div><tsxDom></tsxDom></div>
</template><script setup lang="ts">
import tsxDom from "@/tsx/index";
</script><style scoped></style>

在页面上渲染的结果如下:
在这里插入图片描述

2.2. 使用 vue 中的语法

2.2.1. {} 语法

// index.tsx
// tsx 中使用{}语法
import { ref } from "vue";let hello = ref<string>("Hello, world!");
const tsxDom = () => {return (<><div><h1>{hello.value}</h1><p>This is a tsx.</p></div></>);
};export default tsxDom;

2.2.2. v-model 使用

注意:使用 v-model 时,需要 .value 获取值

// index.tsx
// tsx 中使用 v-model 语法
import { ref } from "vue";
let hello = ref<string>("Hello, world!");const tsxDom = () => {return (<><input type="text" v-model={hello.value} /></>);
};export default tsxDom;

2.2.3. v-show 使用

注意:使用 v-show 时,需要 .value 获取值

// index.tsx
// tsx 中使用 v-show 语法
import { ref } from "vue";
let flag = ref<boolean>(false);const tsxDom = () => {return (<><div v-show={flag.value}>显示</div><div v-show={!flag.value}>隐藏</div></>);
};export default tsxDom;

2.2.4. v-if 不支持,实现v-if功能

使用v-if时,报错:

![在这里插入图片描述](https://img-blog.csdnimg.cn/e9096405f14b4bc189b0ac8742cbb085.png

此时需要采用三元运算来实现 v-if 的功能:

// tsx 中模拟 v-if 语法
import { ref } from "vue";
let flag = ref<boolean>(false);const tsxDom = () => {return <>{flag.value ? <div>显示</div> : <div>隐藏</div>}</>;
};export default tsxDom;

2.2.5. v-for 不支持,实现 v-for 功能

// tsx 中模拟 v-for 语法
import { reactive } from "vue";
interface Data {name: string;age: number;
}
let list = reactive<Data[]>([{ name: "张三", age: 12 },{ name: "李四", age: 18 },
]);const tsxDom = () => {return (<>{{/* 此处完全遵循 react 语法即可 */}list.map((item) => {return <div>{item.name}</div>;})}</>);
};export default tsxDom;

2.2.6. v-bind 不支持,模拟 v-bind

  • 使用时,用 {} 包裹
  • 以 data- 开头的自定义属性
// tsx 中模拟 v-bind 语法
import { reactive } from "vue";interface List {name: string;age: number;
}let list = reactive<List[]>([{name: "张三",age: 10,},{name: "李四",age: 18,},
]);const tsxDom = () => {return (<>{list.map((item) => {return <div data-name={item.name}>{item.age}</div>;})}</>);
};export default tsxDom;

渲染效果如下:
在这里插入图片描述

2.2.7. v-on 使用

  • jsx/tsx中事件的使用与 react 一致
  • 以 on 开头
  • 接收一个回调函数
    注意:不能使用vue中的修饰符
// tsx 中模拟 v-on 语法const handleClick = () => {console.log("被点击了");
};const tsxDom = () => {return (<><button onClick={() => handleClick()}>点击</button></>);
};export default tsxDom;

测试效果如下:

在这里插入图片描述

2.2.8. Props 使用

  • 通过父组件传递参数
  • jsx/tsx接收props并使用
// tsx.vue
<template><div><tsxDom :userName="userName" :userAge="userAge"></tsxDom></div>
</template><script setup lang="ts">
import { ref } from "vue";
import tsxDom from "@/tsx/props";const userName = ref<string>("张三");
const userAge = ref<number>(18);
</script><style scoped></style>
// props.tsx
// tsx 中接收及使用props
interface Props {userName?: string;userAge?: number;
}const handleClick = (props: Props) => {console.log(props);
};const tsxDom = (props: Props) => {return (<><div>{props.userName}</div><div>{props.userAge}</div><button onClick={() => handleClick(props)}>点击</button></>);
};export default tsxDom;

测试效果如下:
在这里插入图片描述

2.2.9. Emit 使用

  • jsx/tsx组件中通过第二个参数 ctx 拿到 emit 方法
  • 通过 emit() 方法传递一个自定义事件以及参数
  • 父组件通过 v-on:自定义事件 拿到传递过来的值
// tsx.vue
<template><div><tsxDom:userName="userName":userAge="userAge"@on-click="handleClick"></tsxDom></div>
</template><script setup lang="ts">
import { ref } from "vue";
import tsxDom from "@/tsx/emit";const userName = ref<string>("张三");
const userAge = ref<number>(18);const handleClick = (value: string) => {console.log(value); // 张三
};
</script><style scoped></style>

tsx 中通过emit给父组件传参

// emit.tsx
interface Props {userName?: string;userAge?: number;
}const handleClick = (props: Props, ctx: any) => {ctx.emit("on-click", props.userName);
};const tsxDom = (props: Props, ctx: any) => {return (<><div>{props.userName}</div><div>{props.userAge}</div><button onClick={() => handleClick(props, ctx)}>点击</button></>);
};export default tsxDom;

2.2.10. v-slot 使用

  • 子组件通过 centex.slots 传参
  • 父组件通过 v-slots={} 接收参数
import { defineComponent, reactive } from "vue";const state = reactive({ name: "张三" });
const list = reactive([1, 2, 3]);export const tsxDom = (props: any, ctx: any) => (<>{/* 默认插槽 */}<div>{ctx.slots.default ? ctx.slots.default() : "默认"}</div>{/* 声明名称为state的插槽 并传值,不传值为ctx.slots.state() */}<div>{ctx.slots.state && ctx.slots.state(state)}</div>{/* 声明名称为list的插槽 并传值,不传值为slots.list() */}<div>{ctx.slots.list && ctx.slots.list(list)}</div></>
);export default defineComponent({setup() {type State = {name: string;};// 使用插槽const slots = {// default: () => <div>匿名插槽</div>,state: (state: State) => <div>{state.name}</div>,list: (list: number[]) => list.map((item) => <div>{item}</div>),};return () => (<>{/* 引用组件, 使用插槽:v-slots={slots} */}<tsxDom v-slots={slots} /></>);},
});

测试效果如下:


在这里插入图片描述

总结

在 Vue3 中,我们可以选择使用模板语法、渲染函数或 JSX 语法来定义组件的模板。使用哪种方式取决于我们的个人喜好和项目的需求。渲染函数可以让我们更加灵活地定义组件的模板,并且可以让我们在编写组件时使用 JavaScript 的全部语言特性。JSX 语法是一种将 XML 语法嵌入到 JavaScript 中的语法,可以让我们更加灵活地定义组件的模板。


http://www.ppmy.cn/news/93371.html

相关文章

人工智能值不值得学习?人工智能就业方向及前景

人工智能值不值得学习? 一、人工智能值得学吗&#xff1f; 很多同学想要知道人工智能值得学吗&#xff1f;小编认为是值得的&#xff0c;具体原因有以下两点&#xff1a; 1、人工智能专业前景好&#xff0c;但人才紧缺 根据人工智能行业的专家预计&#xff0c;到2020年&am…

判断字符串变量是否等于某几个字符串常量值中的任意一个

目录 需求写法一&#xff1a;ifequals写法二&#xff1a;Switch-case写法三&#xff1a;Collection.contains( )写法四&#xff1a;StringUtils.equalsAny( ) 需求 判断某个字符串变量是否等于某几个常量值中的任意一个 举个例子&#xff0c;食材供应商只供应食堂以下8种食材…

jQuery-attr()、val()、add()属性和each函数

<!DOCTYPE HTML> <html> <head> <meta http-equiv"Content-Type" content"text/html; charsetUTF-8"> <title>jQuery-attr()、add()属性和each函数</title> <script type"text/j…

提醒!手机卡注销前,一定要做的四件事!

现在更换手机卡的情况对小伙伴们来说都是家常便饭的事情了&#xff0c;但是很多小伙伴在手机换号的时候&#xff0c;经常忘记解绑以前手机号绑定的一些业务&#xff0c;为此产生了很多不必要的麻烦&#xff0c;今天的这篇文章就是要告诫大家换号之前一定要做的几件事&#xff0…

通过ChatGPT跟MetaHuman对话,Android/iOS兼容

一、申请ChatGPT的API-KEY 1.通过 openAI官网申请API-KEY 2.参考使用腾讯云函数一分钟搭建 OpenAI 免翻墙代理搭建openAI免翻墙代理 3.通过Postman测试一下openAI函数是否可被调用,传入BearerToken和Body参数,ChatGPT即可返回应答数据 二、启用必要的插件 1.启用文字转语…

Java 文档注释

Java支持三种注释方式。前两种分别是// 和/* */&#xff0c;第三种被称作说明注释&#xff0c;它以/** 开始&#xff0c;以 */结束。 说明注释允许你在程序中嵌入关于程序的信息。你可以使用javadoc工具软件来生成信息&#xff0c;并输出到HTML文件中。 说明注释&#xff0c;…

性能优化 面试

性能分析 1.页面加载性能&#xff08;加载时间&#xff1b;用户体验&#xff09; 2.动画与操作性能&#xff08;是否流畅无卡顿&#xff09; 3.内存占用&#xff08;内存占用过大&#xff0c;浏览器崩掉等&#xff09; 4.电量消耗&#xff08;游戏方面&#xff0c;暂不考虑&…

语义分割实战项目(从原理到代码环境配置)

MMsegmentation是一个基于PyTorch的图像分割工具库,它提供了多种分割算法的实现,包括语义分割、实例分割、轮廓分割等。MMsegmentation的目标是提供一个易于使用、高效、灵活且可扩展的平台,以便开发者可以轻松地使用最先进的分割算法进行研究和开发。 看下结果 MMsegmenta…