您好,登錄后才能下訂單哦!
這篇文章主要介紹“Vue3+Vite中如何使用JSX”的相關知識,小編通過實際案例向大家展示操作過程,操作方法簡單快捷,實用性強,希望這篇“Vue3+Vite中如何使用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));
Vue 使用單文件組件,把 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 語法編譯過程中的完整性。
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 或 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 <h2>Hello, { name }</h2>
} else {
return <h2>Hello, Stranger</h2>
}
}
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>
關于“Vue3+Vite中如何使用JSX”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識,可以關注億速云行業資訊頻道,小編每天都會為大家更新不同的知識點。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。