• 如何在 Vue 中使用 JSX 以及使用它的原因


    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>
         }
     }

    广州设计公司https://www.houdianzi.com 我的007办公资源网站https://www.wode007.com

    如何使 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"]
       }
     }
  • 相关阅读:
    H5,JS国际化网站中英文切换
    DIV右上角标签的CSS3实现技巧
    .NET Core也是国产化信息系统开发的重要选项
    微软自家的.Net下的JavaScript引擎--- ClearScript
    Java 生态碎片化 和 .NET生态的一致性
    使用 .NET 进行游戏开发
    .NET 是信息技术应用创新产业重要参与者
    Chrome 80+ 跨域Samesite 导致的cookie not found 解决方法
    在腾讯云云函数计算上部署.NET Core 3.1
    腾讯云 云开发 部署 Blazor网站
  • 原文地址:https://www.cnblogs.com/qianxiaox/p/13831053.html
Copyright © 2020-2023  润新知