Author:ManStruggling
什么是 JSX?
JSX 是一种 JavaScript 和 XML 的联合,即 JavaScript + XML = JSX,JSX 源于 Facebook,能够在 JavaScript 里写 XML,因为这个个性,所以具备了 JavaScript 的灵活性,同时又兼具 html 的语义化和直观性
为什么应用 JSX?
- jsx 比照 createElement 函数可读性更强;<div></div> VS this.$createElement(‘div’, {…}, […])
- vue-cli3.0 及以上默认反对 jsx 语法
- jsx 能够使 vue 组件更容易导入和治理
首先来横向比照一下 <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>
createElement
createElement 函数实际上创立的是 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
,在 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
这里就不做 createElement 函数的阐明了,想必也没有多少人用这个吧。。。。有的话,那你赢了
JSX
template 模板代码超过三百行,就很难浏览了,会反复在 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 反对一下小编,心愿小编的内容对大家有所帮忙~
[TOC]