使用JSX写Vue组件(1)

1,709 阅读3分钟

这是我参与11月更文挑战的第1天,活动详情查看:2021最后一次更文挑战

JSX是什么

JavaScript + XML = JSX

是一种 HTML-in-JavaScript 的语法,既不是字符串也不是 HTML,是属于 JavaScript 语法上的拓展

利用 JSX,在 React 使用 JavaScript,来声明元素(构成 React 应用的最小单位),继而描述用户页面

建议将JSX与 React 一起使用来描述 UI 应该是什么样子。JSX 可能会让您想起 模板语言,但它具有 JavaScript 的全部功能。JSX 产生 React “元素”,可将它们渲染到 DOM

为何在Vue中使用JSX

(可能会有这样的疑惑:在Vue中用JSX,不如选 React……)

来个声明

首先,此文并不是推崇用 JSX 作为主流去进行 Vue 开发,放弃 SFC 的优势

Vue 推荐在绝大多数情况下使用模板(template)来创建你的 HTML

尤大大在某乎点赞了文章:# 前端开发,为什么我支持模板而不是JSX。

image.png

作者提到几点原因:

  • 需要 JSX 的情况,往往是出现在不合格的设计
  • 需额外考虑 JSX 编译为虚拟 DOM 的执行情况
  • View 与 Model 通过 ViewModel 实现双向绑定,但 JSX 是偏向模板和逻辑分离的写法
  • 性能方面:JSX 过度的灵活性,编译阶段难优化
    • 补充:Vue 3.x,在编译优化方面:重写了 diff 算法,编译生成了 Block tree,性能有更大的提升

辅助角色

一枚硬币有正反两面,JSX 虽然有明显的缺点,但是相对而言,也存在一定的优点

先来看看一个需求场景:根据判断,从多个组件中选择一个来渲染 (基于 Vue 2.x)

进行以下选择:

  • template模板

    • 有几种条件判断结果就有几个条件判断,可能会是 v-if => v-else-if => …… => v-else,template较长,略笨重

    • 基于上述,把每个组件都抽离出来为子组件,单独为一个.vue文件,再用上动态组件,template是简化了,但组件引用多了

    • 如果抽离的子组件都不算太复杂,加上复用性不大(假设就为此需求服务),就需考虑抽离的必要性

  • render函数

    • 即使结构使较简单的情况下,render 函数的写法也变得复杂,不够直观,可读性差

     return h("div", [
           h(
             "el-button",
             {
               props: { plain: true },
               style: { marginRight: "10px" }
             },
             "Hello World"
           )
     ]);
    
    • 条件判断较多,代码量一大,写起来更为痛苦,果断放弃
  • JSX

    • template 和 render 的方案都觉得不太合适,试试在 components 选项中用 JSX 写个小组件
    components: {
        demoChild: {
            props:{//……},
            render() {
                const events = { on: { click: (e) => console.log(e) } };
                return (
                  <div>
                    <el-button plain style="{margin-right: 10px}">
                      Hello World
                    </el-button>
                    <el-button type="info" {...events}>
                      Hello JSX
                    </el-button>
                  </div>
                );
            } 
        }
    }
    

    可以看出:JSX 写法与 template 模板类似,相对而言:

    • 可读性提高,避免较笨重的 template 写法

    • 可减少组件引入,避免不必要的抽离

所以,个人认为,JSX 灵活性高,一定程度上,Vue开发中可作为辅助手段

案例

element-ui 组件库的开发中,更为直观地使用 JSX 的有:submenu、avatar,等等

submenu源码如:

// 无template
<script>
  // ……
  render(h) {
    const popupMenu = (
      <transition name={menuTransitionName}>
        <div>……</div>
      </transition>
    );
    const inlineMenu = (
      <el-collapse-transition>
        <ul>……</ul>
      </el-collapse-transition>
    );

    return (
      <li>
        <div
          class="el-submenu__title"
          ref="submenu-title"
          on-click={this.handleClick}
          on-mouseenter={this.handleTitleMouseenter}
          on-mouseleave={this.handleTitleMouseleave}
          style={[paddingStyle, titleStyle, { backgroundColor }]}
        >
          {$slots.title}
          <i class={["el-submenu__icon-arrow", submenuTitleIcon]}></i>
        </div>
        {this.isMenuPopup ? popupMenu : inlineMenu}
      </li>
    );
  }
</script>

链接传送门

# Reactjs - 介绍 JSX

# 前端开发,为什么我支持模板而不是JSX。

# 傲慢才是阻碍技术提升的最大障碍

# Github - element

Last but not least

如有不妥,请多指教呀~