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]