在 Vue 中使用 JSX 及使用它的原因浅析


Posted in Javascript onFebruary 10, 2020

本文 GitHub https://github.com/qq44924588... 上已经收录,更多往期高赞文章的分类,也整理了很多我的文档,和教程资料。欢迎Star和完善,大家面试可以参照考点复习,希望我们一起有点东西。

Vue.js 具有简单的 API 和几个选项,可用于在我们的组件中定义HTML模板。

我们可以使用 <template> 标签选项,在根组件实例上定义 template 属性,或者使用单文件组件。

上面的选项很棒并且可以完美地工作,但是,在您的应用程序的生命周期中,有时会感到笨拙,设计过度或非常不灵活。

那么,我们为什么要使用 JSX 而不是其他模板定义呢?

  • JSX 更易读, <div></div> 的写法一看就是比 this.$createElement('div', {}, [...]) 简洁很多。
  • JSX 也是 JavaScript。
  • Vue支持JSX。
  • JSX 使自定义 Vue 组件更容易导入和管理。

简介

先举一个例子来说明为什么 JSX 是好的。

我们要构建一个 <TextField/> 组件,该组件可以是普通的单行文本输入或多行输入(文本区域)。 我们的模板声明可能看起来像这样。

<div>
 <textarea v-if="multiline" v-model="content" :name="name" :placeholder="placeholder" :aria-invalid="false">
 <input v-else v-model="content" :name="name" :placeholder="placeholder" :aria-invalid="false">
 </div>

从上面的代码片段中可以看到,我们很快就会遇到一些问题,比如重复代码等等。想象一下,必须支持 input 上面所列的各种属性。上面的这个小片段将会增长并成为一个难以维护的噩梦。

要解决这个问题,我们需要使用Vue进行降级处理,因此需要使用理接近Vue的内部API来解决这个问题。

render() 方法

注意:这里并不是说没有JSX就没有一种简单的方法来处理上面的问题,只是说将这个逻辑移动到带有JSX的 render() 方法可以使组件更直观。

我们在 Vue 中创建的每个组件都有一个 render 方法。这个就是 Vue 选择渲染组件的地方。即使我们不定义这个方法,Vue 也会为我们做这件事。

这意味着当我们在 Vue 中定义 HTML 模板时,Vue 的模板编译器将其编译为一个 createElement 函数,该函数带有几个参数并从 render 函数返回结果。

为了修复上一节中的代码,我们删除了 template 属性或 template 标签,并在组件上定义了 render() 方法。 如果在组件上定义了 render 方法,则 Vue 将忽略 template 定义。

...
 export default {
  name: 'TextField',
  render (createElement) {
   const tag = this.multiline ? 'textarea' : 'input'

  return createElement(tag, {
    class: {
     'text-input': true,
     'is-disabled': false
    },
    attrs: {
     name: this.name,
     placeholder: this.placeholder,
     'aria-invalid': false
    }
   })
  } 
 }
...

上面的代码做了几件事:

  1. render 方法从Vue获取一个 createElement 助手。
  2. 我们以编程方式定义我们的标签。
  3. 然后,我们创建标签并将其属性,类等作为对象传递。 我们可以传递给 createElement 的 选项 很多。
  4. 我们返回新创建的元素进行渲染。

我们为 Vue 组件定义的每个模板都将转换为可返回 createElement 函数的 render 方法。 因为这个原因, render 方法将优先于模板定义。

举个例子:

// HTML
<div>
 <p>Only you can stop forest fires</p>
</div>

模板编译器将把上面的 HTML 转换成:

...
render (createElement) {
 return createElement(
 'div',
 {},
 createElement(
  'p',
  {},
  'Only you can stop forest fires'
 )
 )
}
...

现在你可能会问这个问题:“对可读性来说这不好吗?” 答案是肯定的。 一旦定义了具有许多元素嵌套级别或具有多个同级元素的组件,我们就会遇到这个新问题。

这就是 JSX 出现的原因,它可以很好的解决此类问题。

JSX 是什么

JSX 是 Facebook 工程团队创造的一个术语。

JSX 是 JavaScript 的类似XML的语法扩展,没有任何定义的语义。

JSX 不打算由引擎或浏览器实现。相反,我们将使用 Babel 之类的转置器将JSX转换成常规的 JS 。

// 此行是JSX的示例
const heading = <h1>Welcome to Scotch</h1>;

基本上,JSX 允许我们在 JS 中使用类似 Html 的语法。

配置 Vue 以使用 JSX

如果使用的 Vue-cli 大于或等于 3.0 版本,那么就直接可以使用JSX的语法了。

如果您使用的是不支持 JSX 的Vue-cli较旧版本,则可以通过安装 babel-preset-vue-app 来添加它,并将其添加到您的 .babelrc 文件中。

# Using npm
 npm install --save-dev babel-preset-vue-app
# Using yarn
 yarn add --dev babel-preset-vue-app

在 .babelrc 文件中,添加:

{
 "presets": ["vue-app"]
}

我们现在可以在组件的 render 函数中使用 JSX。

在 Vue 中使用 JSX 需要注意的地方
在 Vue 中使用JSX需要注意几点。

要监听 JSX 中的事件,我们需要 “on” 前缀。 例如,将 onClick 用于单击事件。

render (createElement) {
  return (
   <button onClick={this.handleClick}></button>
  )
 }

要修改事件,请使用

render (createElement) {
  return (
   <button onClick:prevent={this.handleClick}></button>
  )
 }

绑定变量,注意这里不是使用 :

render (createElement) {
  return (
   <button content={this.generatedText}></button>
  )
 }

将HTML字符串设置为元素的内容,使用 domPropsInnerHTML 而不是使用 v-html

render (createElement) {
  return (
   <button domPropsInnerHTML={htmlContent}></button>
  )
 }

我们也可以展开一个大对象:

render (createElement) {
  return (
   <button {...this.largeProps}></button>
  )
 }

在 render 中使用JSX

回到我们最初的 “TextField” 组件。现在我们已经在 Vue 应用程序中启用了 JSX,我们现在可以这样做了。

render (createElement) {
  const inputAttributes = {
   class: 'input-field has-outline', // class definition
   onClick: this.handleClick // event handler
   backdrop: false // custom prop
  }
  const inputMarkup = this.multiline
   ? <textarea {...inputAttributes}></textarea>
   : <input {...inputAttributes}/>
 return inputMarkup
 }

导入 Vue JS 组件

在 Vue 中使用JSX的另一个好处是,我们不再需要注册所需的每个组件。 我们只是导入和使用。

import {Button} from '../components'

export default {
  render (createElement) {
   return <Button primary={true}>Edit</Button>
  }
 }

如何使 JSX 与 TypeScript 一起使用

TypeScript 用作一种向 JavaScript添加类型检查的机制。要在 JSX 支持 TypeScript中,需要修改 tsconfig.json 。

要在 TypeScript 中启用 JSX,请先将该文件另存为 .tsx 文件,然后将 tsconfig.json 修改为包括:

{
 "compilerOptions": {
  ....
  "jsx": "preserve",
 }
 }

将 jsx 选项设置为 “preserve” 意味着 TypeScript 不应处理JSX。 这样做使 Babel 可以控制所有JSX 和 TypeScript 坚持使用类型,因为它尚不支持 Vue JSX。

然后在项目中创建一个 jsx.d.ts 文件,并为 Vue 添加 TypeScript JSX 声明。

import Vue, {VNode} from 'vue'

declare global {
 namespace JSX {
  interface Element extends VNode {}
  interface ElementClass extends Vue {}
  interface ElementAttributesProperty {
  $props: {}
  }
  interface IntrinsicElements {
 [elemName: string]: any
  }
 }
 }

确保 TypeScript 可以加载声明文件。 或者,可以通过以下方式在 tsconfig.json 中为其添加自动加载功能:

{
 "compilerOptions": {
  ...
  "typesRoot": ["./node_modules/@types", "./types"]
 }
 }

代码部署后可能存在的BUG没法实时知道,事后为了解决这些BUG,花了大量的时间进行log 调试,这边顺便给大家推荐一个好用的BUG监控工具 Fundebug 。

总结

以上所述是小编给大家介绍的在 Vue 中使用 JSX 及使用它的原因浅析,希望对大家有所帮助!

Javascript 相关文章推荐
8个实用的jQuery技巧
Mar 04 Javascript
node.js中的fs.lchownSync方法使用说明
Dec 16 Javascript
jquery通过load获取文件的内容并跳到锚点的方法
Jan 29 Javascript
关于Bootstrap弹出框无法调用问题的解决办法
Mar 10 Javascript
Node.js中使用jQuery的做法
Aug 17 Javascript
JS实现iframe自适应高度的方法示例
Jan 07 Javascript
Angular.Js之Scope作用域的学习教程
Apr 27 Javascript
echarts饼图扇区添加点击事件的实例
Oct 16 Javascript
Vue响应式原理深入解析及注意事项
Dec 11 Javascript
仿淘宝JSsearch搜索下拉深度用法
Jan 15 Javascript
JavaScript交换两个变量方法实例
Nov 25 Javascript
jQuery实现倒计时功能完整示例
Jun 01 jQuery
node.js使用http模块创建服务器和客户端完整示例
Feb 10 #Javascript
webpack打包优化的几个方法总结
Feb 10 #Javascript
JS+HTML5本地存储Localstorage实现注册登录及验证功能示例
Feb 10 #Javascript
node.js制作一个简单的登录拦截器
Feb 10 #Javascript
使用 Vue-TCB 快速在 Vue 应用中接入云开发的方法
Feb 10 #Javascript
jQuery实现简易QQ聊天框
Feb 10 #jQuery
解决vue-cli@3.xx安装不成功的问题及搭建ts-vue项目
Feb 09 #Javascript
You might like
php初学者写及时补给skype用户充话费的小程序
2008/11/02 PHP
CI(CodeIgniter)框架介绍
2014/06/09 PHP
基于Laravel实现的用户动态模块开发
2017/09/21 PHP
Yii框架模拟组件调用注入示例
2019/11/11 PHP
extjs 学习笔记(一) 一些基础知识
2009/10/13 Javascript
两种不同的方法实现js对checkbox进行全选和反选
2014/05/13 Javascript
JavaScript eval() 函数介绍及应用示例
2014/07/29 Javascript
javascript实现多栏闭合展开式广告位菜单效果实例
2015/08/05 Javascript
Javascript刷新窗口方法小结
2015/10/21 Javascript
Bootstrap CDN和本地化环境搭建
2016/10/26 Javascript
js倒计时显示实例
2016/12/11 Javascript
使用gulp搭建本地服务器并实现模拟ajax
2017/04/05 Javascript
vue中阻止click事件冒泡,防止触发另一个事件的方法
2018/02/08 Javascript
解决iView中时间控件选择的时间总是少一天的问题
2018/03/15 Javascript
Angular使用过滤器uppercase/lowercase实现字母大小写转换功能示例
2018/03/27 Javascript
微信小程序中换行空格(多个空格)写法详解
2018/07/10 Javascript
JavaScript基于SVG的图片切换效果实例代码
2020/12/15 Javascript
[02:17]TI4西雅图DOTA2前线报道 啸天mik夫妻档解说
2014/07/08 DOTA
[03:01]2014DOTA2国际邀请赛 小组赛7月13日TOPPLAY
2014/07/14 DOTA
Python写的英文字符大小写转换代码示例
2015/03/06 Python
python xlsxwriter创建excel图表的方法
2018/06/11 Python
Django contenttypes 框架详解(小结)
2018/08/13 Python
使用Matplotlib 绘制精美的数学图形例子
2019/12/13 Python
pycharm中导入模块错误时提示Try to run this command from the system terminal
2020/03/26 Python
Python实现自动签到脚本的示例代码
2020/08/19 Python
IE下实现类似CSS3 text-shadow文字阴影的几种方法
2011/05/11 HTML / CSS
HTML5实现桌面通知 提示功能
2017/10/11 HTML / CSS
时尚圣经:The Fashion Bible
2019/03/03 全球购物
毕业生物理教师求职信
2013/10/17 职场文书
《陈毅探母》教学反思
2014/05/01 职场文书
大学生应聘导游自荐信
2014/06/02 职场文书
论文致谢词范文
2015/05/14 职场文书
2016优秀护士求职自荐信
2016/01/28 职场文书
《观察物体》教学反思
2016/02/17 职场文书
python脚本框架webpy的url映射详解
2021/11/20 Python
「魔法少女伊莉雅」美游粘土人开订
2022/03/21 日漫