您好,欢迎访问一九零五行业门户网

详解Vue3+Vite中怎么使用JSX

vue+vite中怎么使用jsx?下面本篇文章给大家介绍一下vue3+vite 中 jsx 的使用方式,希望对大家有所帮助!
【相关推荐:vuejs视频教程、web前端开发】
jsx介绍jsx(javascript 和 xml),是一个 html-in-javascript 的语法扩展,首先在 react 中被进入。jsx 可以很好地描述 ui 应该呈现出它应有交互的本质形式。jsx 是在 javascript 语法上的拓展,因此类似于 html 的代码可以和 js 共存。例如:
const button = <mybutton color="blue" shadowsize={2}> click me</mybutton>
该 button 常量称为 jsx 表达式。可以使用它在我们的应用程序中渲染 <mybutton> 标签。浏览器是无法读取直接解析 jsx 的。jsx 表达式经过( babel 或 parcel 之类的工具)编译之后是这样的:
react.createelement( mybutton, {color: 'blue', shadowsize: 2}, 'click me')
实际上,jsx 仅仅只是 react.createelement(component, props, ...children) 函数的语法糖。可以使用 react.createelement() 自己编写 ui 来跳过编译步骤。但是,这样做会失去 jsx 的声明性优势,并且代码变得更难以阅读。编译是开发过程中的一个额外步骤,但是 react 社区中的许多开发人员都认为 jsx 的可读性值得。另外,流行的工具使 jsx-to-javascript 编译成为其设置过程的一部分。除非您愿意,否则不必自己配置编译。如果你想测试一些特定的 jsx 会转换成什么样的 javascript,你可以尝试使用 在线的 babel 编译器。
react 并不强制要求使用 jsx。当你不想在构建环境中配置有关 jsx 编译时,不在 react 中使用 jsx 会更加方便。例如,用 jsx 编写的代码:
class hello extends react.component { render() { return <div>hello {this.props.towhat}</div>; }}const root = reactdom.createroot(document.getelementbyid('root'));root.render(<hello towhat="world" />);
可以编写为不使用 jsx 的代码:
class hello extends react.component { render() { return react.createelement('div', null, `hello ${this.props.towhat}`); }}const root = reactdom.createroot(document.getelementbyid('root'));root.render(react.createelement(hello, {towhat: 'world'}, null));
在 vue3 中使用 jsxvue 使用单文件组件,把 template 模板、相关脚本和 css 一起整合放在 .vue 结尾的一个单文件中。这些文件最终会通过 js 打包或构建工具(例如 webpack、vite)处理。
<template> 元素包含了所有的标记结构和组件的展示逻辑。template 可以包含任何合法的 html,以及 vue 特定的语法。通过设置 <template> 标签的 lang 属性,例如可以通过设置 <template lang="pug"> 就可以在使用 pug 模板来替代标准 html。
而 .vue 文件中的 <script> 标签包含组件中所有的非显示逻辑,并且需要默认导出一个 js 对象。该对象是在本地注册组件、定义属性、处理本地状态、定义方法等的地方。在构建阶段这个包含了 template 模板的对象会被处理和转换成为一个有 render() 函数的 vue 组件。
组件的 css 样式写在 <style> 标签里,如果添加了 scoped 属性,vue 会把样式的范围限制到单文件组件的内容里。这是类似于 css-in-js 的解决方案,只不过允许书写纯粹的 css。如果通过 cli 创建项目时选择了 css 预处理器,则可以将 lang 属性添加到 <style> 标签中,以便 webpack 可以在构建时处理内容。
虽然 jsx 最早是由 react 引入,但实际上 jsx 语法并没有定义运行时语义,并且能被编译成各种不同的输出形式。如果你之前使用过 jsx 语法,那么请注意 vue 的 jsx 编译方式与 react 中 jsx 的编译方式不同,因此不能在 vue 应用中使用 react 的 jsx 编译。与 react jsx 语法的一些明显区别包括:
可以使用 html attributes 比如 class 和 for 作为 props - 不需要使用 classname 或 htmlfor。传递子元素给组件 (比如 slots) 的方式不同。vue 的类型定义也提供了 tsx 语法的类型推导支持。当使用 tsx 语法时,确保在 tsconfig.json 中配置了 "jsx": "preserve",这样的 typescript 就能保证 vue jsx 语法编译过程中的完整性。
安装插件(@vitejs/plugin-vue-jsx)vite 官方提供了官方的插件来支持在 vue3 中使用 jsx/tsx,直接安装就行。
npm i @vitejs/plugin-vue-jsx -d
安装完之后在 vite.config.js 文件中的 plugins 字段中添加 jsx 支持:
import vuejsx from "@vitejs/plugin-vue-jsx";export default defineconfig({ plugins: [ vuejsx(), ]})
这样就可以在项目中使用 jsx/tsx 了。
新建 jsx 文件在项目中新建 jsx 或 tsx 后缀的文件,语法和 js 文件类似,但是和 .vue 文件中的 <script> 标签一样需要默认导出一个 js 对象。该对象是在本地注册组件、定义属性、处理本地状态、定义方法等的地方。
import helloworld from './helloworld.vue'export default { setup() { return () => <helloworld msg="11" />; },};
语法1、插值。与 vue 模板语法中的插值一样,但是双大括号 {{}} 变为了单大括号 {}。大括号内支持任何有效的 javascript 表达式,比如:2 + 2,user.firstname,formatname(user) 等。
// 模板语法<span>{{ a + b }}</span>// jsx/tsx<span>{ a + b }</span>
2、class 类名绑定。有两种方式,使用模板字符串或者使用数组。
// 模板字符串<div classname={ `header ${ isbg ? 'headerbg' : '' }` }>header</div>// 数组<div class={ [ 'header', isbg && 'headerbg' ] } >header</div>
3、style 样式绑定。需要使用双大括号。
const color = 'red'const element = <sapn style={{ color, fontsize: '16px' }}>style</sapn>
4、条件渲染。由于 jsx 本身具有 js 语法,所以不再需要使用 v-if 指令,使用 if/else 和三元表达式都可以实现。但是支持 v-show 指令。
const element = (name) => { if (name) { return <h1>hello, { name }</h1> } else { return <h1>hello, stranger</h1> }}const element = icon ? <span class="icon"></span> : null;// 以上代码等效于:const element = icon && <span class="icon"></span>;
5、列表渲染。同样,由于 jsx 本身具有 js 语法,所以不再需要使用 v-for 指令,使用 js 数组的 map 方法即可。
const listdata = [ {name: 'tom', age: 18}, {name: 'jim', age: 20}, {name: 'lucy', age: 16}]return () => ( <div> <div class={'box'}> <span>姓名</span> <span>年龄</span> </div> { prop.listdata.map(item => <div class={'box'}> <span>{item.name}</span> <span>{item.age}</span> </div> }) </div>)
6、标签属性绑定。也是使用大括号包裹,不能使用 v-bind 指令。而 vue 组件中通过 <div v-bind="properties"></div> 批量绑定标签属性,在 jsx 中需要使用 <div {...properties}></div>。
const href = 'https://cn.vuejs.org/'const element = <a href={href}>vue3</a>
7、事件绑定。使用的也是 单大括号 {},不过事件绑定不是以 @为前缀了,而是改成了 on,与原生相同。例如:click 事件是 onclick 或 onclick。
const confirm = () => { // 确认提交}<button onclick={confirm}>确定</button>
如果要带参数,需要使用箭头函数进行包裹:
const confirm = (name) => { // 确认提交}<button onclick={() => confirm('are you sure')}>确定</button>
8、事件修饰符。需要使用 withmodifiers 方法,接收两个参数,第一个参数是绑定的事件,第二个参数是需要使用的事件修饰符。
import { withmodifiers, definecomponent, ref } from 'vue'const app = definecomponent({ setup() { const count = ref(0); const inc = () => { count.value++; }; return () => ( <div onclick={ withmodifiers(inc, ['self']) }>{ count.value }</div> ); },})export default app
注意:vue 模板中 ref 变量是可以直接解构的,但是在 jsx 中不行,需要添加 .value,比如上面的 { count.value }。
9、v-model 双向绑定。需要使用单大括号 {}。如果绑定属性则需要一个数组,第一个元素为绑定的值,第二个元素为绑定的属性。
// 绑定值<input v-model="show" /> // vue<input v-model={show.value} /> // jsx// 绑定属性<input v-model:prop="show" /> // vue<input v-model={[show.value,'prop']} /> // jsx// 修饰符写法<input v-model:prop.trim="show" /> // vue<input v-model={[show.value,'prop',['trim']]} /> // jsx
10、slot 插槽。jsx/tsx 中无法使用 slot 标签,定义插槽方式一:通过 setup 函数的第一个参数 ctx 上下文对象的 slots 的属性,setup 函数默认接收两个参数:
props - 组件传入的参数对象。ctx - 上下文对象,上下文对象暴露了其他一些在 setup 中可能会用到的值,包括:attrs - 透传的 attributes(非响应式的对象,等价于 $attrs)。slots - 插槽(非响应式的对象,等价于 $slots)。emit - 触发事件的函数(等价于 $emit)。expose - 暴露公共属性的函数。如果解构了 props 对象,解构出的变量将会丢失响应性,因此推荐通过 props.xxx 的形式来使用其中的 props。如果确实需要解构 props 对象,或者需要将某个 prop 传到一个外部函数中并保持响应性,可以使用 torefs() 和 toref() 这两个工具函数:
import { torefs, toref } from 'vue'export default { setup(props) { // 将 `props` 转为一个其中全是 ref 的对象,然后解构 const { title } = torefs(props) // `title` 是一个追踪着 `props.title` 的 ref console.log(title.value) // 或者,将 `props` 的单个属性转为一个 ref const title = toref(props, 'title') }}
ctx 上下文对象是非响应式的,可以安全地解构:
export default { setup(props, { attrs, slots, emit, expose }) { ... }}
attrs 和 slots 都是响应式(有状态)的对象,它们总是会随着组件自身的更新而更新。这意味着你应当避免解构它们,并始终通过 attrs.x 或 slots.x 的形式使用其中的属性。此外,和 props 不同,attrs 和 slots 的属性都不是响应式的。如果想要基于 attrs 或 slots 的改变来执行副作用,那么应该在 onbeforeupdate 生命周期钩子中编写相关逻辑。
expose 函数用于显式地限制该组件暴露出的属性,当父组件通过模板引用访问该组件的实例时,将仅能访问 expose 函数暴露出的内容:
export default { setup(props, { expose }) { // 让组件实例处于 “关闭状态” // 即不向父组件暴露任何东西 expose() const publiccount = ref(0) const privatecount = ref(0) // 有选择地暴露局部状态 expose({ count: publiccount }) }}
通过 ctx 上下文对象的 slots 的属性可以获取插槽对象后,就可以定义插槽了。
import { definecomponent } from 'vue'export default definecomponent({ setup(props, { slots }) { // 逻辑 return () => { return <p> <button>{ slots.test?.() }</button> <button>{ slots.default?.() }</button> </p> } },})// 在引用的组件中<template #test>slot-test</template><template #>slot-default</template>
定义插槽方式二:使用 renderslot 函数。
import { renderslot } from 'vue'<button> { renderslot(slots, 'default') }</button>
而如果在 jsx 中使用插槽,可以直接通过标签属性 slot,或通过 v-slots 指令。
import helloworld from './helloworld' export default definecomponent({ setup() { return () => ( <div class={'box'}> <helloworld v-slots={{ title: () => { return <p>我是title插槽</p> }, default: () => { return <p>我是default插槽</p> } }} /> </div> ) } })
11、css modules。引入局部样式,相当于 vue 组件中 <style> 标签的 scoped 属性。
import styles from './index.module.scss'<div class={styles.wrap}></div>
github 源码vue3 中自定义组件(学习视频分享:vuejs入门教程、编程基础视频)
以上就是详解vue3+vite中怎么使用jsx的详细内容。
其它类似信息

推荐信息