作者:ManStruggling
來源:SegmentFault 思否社區
什麼是 JSX?JSX是一種JavaScript和XML的結合,即JavaScript + XML = JSX,JSX源於Facebook,可以在JavaScript裡寫XML,因為這個特性,所以具備了JavaScript的靈活性,同時又兼具html的語義化和直觀性
為什麼使用 JSX?首先來橫向對比一下<template></template>模板語法、createElement函數、jsx三種渲染方式慄子一template模板語法使用最多,不做解釋<div id="vnode">
一些文本
<p class="bar" style="color: red; font-weight: bold;">Only you can stop forest fires</p>
<span>span text</span>
<b>b tag</b>
</div>
createElementcreateElement函數實際上創建的是Virtual Node,創建VNode樹,一旦Dom樹的結構複雜,dom節點屬性太多,勢必會造成可讀性差的問題。。。render(h) {
return h(
"div",
{
attrs: {
id: "vnode",
},
},
[
"一些文本",
h(
"p",
{
class: {
bar: true,
},
style: {
color: "red",
fontWeight: "bold",
},
},
"Only you can stop forest fires"
),
h("span", {}, "span text"),
h("b", { domProps: { innerText: "b tag" } }),
]
);
}JSX然後jsx就閃亮登場render() {
return (
<div id="vnode">
一些文本
<p class="bar" style="color: red; font-weight: bold;">
Only you can stop forest fires
</p>
<span>span text</span>
<b>b tag</b>
</div>
);
}
可能有的同學覺得,就這,跟template沒什麼區別呀。這個案例只涉及到html沒有涉及javascript,jsx是把javascript和html放在一起來書寫的。所以看下個慄子慄子二根據type的值進行條件渲染,A、B、C三個模塊,每個模塊有自己的對應模塊的代碼,也有一些公共的模塊,假設這些代碼有很多行,勢必會造成閱讀性的降低。有人可能覺得如果這樣的話,把公共代碼抽離出一個單獨的組件不就好了,這樣使可以解決問題,如果這裡的公共代碼僅僅只在這一個文件內使用,別的文件不會對這些公共代碼做引用呢,要不要考慮抽離公共組件的必要性呢,jsx就可以完美的解決這些問題。template<div>
<!-- 模塊A -->
<div class="module-a" v-if="type === 0">
<div>
...模塊A的代碼
</div>
<div>
...公共代碼
</div>
</div>
<!-- 模塊B -->
<div class="module-b" v-else-if="type === 1">
<div>
...模塊B的代碼
</div>
<div>
...公共代碼
</div>
</div>
<!-- 模塊C -->
<div class="module-c" v-else>
<div>
...模塊C的代碼
</div>
<div>
...公共代碼
</div>
</div>
</div>
這裡就不做createElement函數的說明了,想必也沒有多少人用這個吧。。。。有的話,那你贏了JSXtemplate模板代碼超過三百行,就很難閱讀了,會重複在VM、V層切換,所以在複雜的大型項目中建議用jsx來做render,提高代碼的可閱讀性render() {
// 提取公共模塊代碼
const renderCommon = () => <div>...公共代碼</div>;
const renderA = () => (
<div class="module-a">
<div>...模塊A的代碼</div>
{renderCommon()}
</div>
);
const renderB = () => (
<div class="module-b">
<div>...模塊B的代碼</div>
{renderCommon()}
</div>
);
const renderC = () => (
<div class="module-c">
<div>...模塊C的代碼</div>
{renderCommon()}
</div>
);
return (
<div>
{this.type === 0 ? renderA() : this.type === 1 ? renderB() : renderC()}
</div>
);
}Usage<script>
export default {
render() {
// 條件渲染
const vIfRender = () => {
let show = false;
return (
<div
id={"test"}
class={{ "test-wrapper": true }}
style={{ fontWeight: "bold" }}
>
{show ? <div>display</div> : "hidden"}
</div>
);
};
// v-html渲染
const vHtmlRender = () => <div domPropsInnerHTML={`<i>i text</i>`}></div>;
const listRencer = () => (
<ol>
{[1, 2, 3, 4, 5].map((item) => (
<li>{item}</li>
))}
</ol>
);
// 事件綁定
const handleParentClick = () => {
console.log("trigger parent click");
};
const handleClick = (e) => {
e.stopPropagation();
console.log("trigger click");
};
const eventBindingRender = () => (
<div onClick={handleParentClick}>
parent text
<button domPropsInnerHTML={"點一下試試"} onClick={handleClick}></button>
</div>
);
// 屬性綁定
const inputAttrs = {
type: "number",
placeholder: "請輸入數字",
};
const attrBindingRender = () => <input {...{ attrs: inputAttrs }} />;
// 指令
const directiveBindingRender = () => (
<button
{...{
directives: [
{
name: "permission",
value: 666,
modifiers: { foo: true },
},
],
}}
>
權限管理
</button>
);
return (
<div>
{
// v-if 三目運算符
vIfRender()
}
{
// v-html
vHtmlRender()
}
{
// 列表渲染
listRencer()
}
{
// 事件綁定
eventBindingRender()
}
{
// 屬性綁定
attrBindingRender()
}
{
// 指令
directiveBindingRender()
}
</div>
);
},
};
</script>
插槽和作用域插槽// child.vue
<script>
export default {
props: {
config: {
type: Object,
required: true
}
},
render() {
return (
<div>
<h3>{this.config.text}</h3>
{this.$scopedSlots.content({
data: this.config.childConfig
})}
</div>
)
}
}
</script><script>
import Child from "./child";
export default {
render() {
const config = {
text: "parent text jsx",
childConfig: {
test: "children text jsx",
},
};
return (
<div>
<Child
config={config}
{...{
scopedSlots: {
content: ({data}) => {
return <div>{data.test}</div>;
},
},
}}
></Child>
</div>
);
},
};
</script>
組件直接引入使用,無需components註冊,方便導入和管理
上述總結使用jsx的一些特殊情況,條件渲染、v-html、列表的渲染、事件的綁定、屬性綁定、指令的使用、插槽和作用域插槽,聰明的你肯定可以看出來,使用jsx能像vue3的composition API一樣把相同的邏輯代碼聚合在一起,避免大型項目開發時,頁面邏輯複雜導致代碼量上升,option API在template和methods之間來回切換的問題。第一次撰文,如有疑問,歡迎各位大佬斧正,希望大家能夠STAR支持一下小編,希望小編的內容對大家有所幫助~點擊左下角閱讀原文,到 SegmentFault 思否社區 和文章作者展開更多互動和交流,掃描下方」二維碼「或在「公眾號後臺「回復「 入群 」即可加入我們的技術交流群,收穫更多的技術文章~