vue vue-jsx标签

Vue.js has an easy API and several options for defining HTML templates in our components.

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

We can use the <template> tag option, define a template property on our root component instance, or use Single-File components.

我们可以使用<template>标记选项,在我们的根组件实例上定义template属性,或者使用Single-File组件 。

The options above are awesome and work perfectly, but, there comes a time in the lifecycle of your application where they either feel clunky, over-engineered or very inflexible.

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

So, why would we want to JSX instead of any of the other template definitions?

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

  • JSX is easy to read. <div>...</div> is subjectively better than this.$createElement('div', {}, [...])

    JSX易于阅读。 <div>...</div>在主观上要优于this.$createElement('div', {}, [...])
  • Seriously, It's just JavaScript.

    说真的,这只是JavaScript。
  • Vue has support for JSX.

    Vue支持JSX。
  • JSX makes custom Vue components easier to import and manage.

    JSX使自定义Vue组件更易于导入和管理。

快速介绍 ( A quick intro )

Let me give you an example of why JSX is good.

让我举一个为什么JSX很好的例子。

We want to build a <TextField/> component that can either be a normal single-line text input or a multiline input (textarea). Our template declaration might look like this.

我们想要构建一个<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>

As you can see from the snippet above, we'll quickly run into a few problems like duplicate code and many more. Imagine having to support a variety of properties on the input. This little snippet above will grow and be a nightmare to maintain.

从上面的代码片段中您可以看到,我们将很快遇到一些问题,例如重复代码等等。 想象一下必须在输入上支持各种属性。 上面的这个小片段将会增长,并且将成为噩梦。

To fix this, we need to go low-level with Vue. We need to get closer to Vue's internal API to fix this mess.

要解决此问题,我们需要对Vue进行低级处理。 我们需要更接近Vue的内部API来解决此问题。

render()方法 ( The render() method )

NOTE: I'm not saying that the there's not a simple way or ways to handle the above problem without JSX, all I'm saying is that moving this logic to the render() method with JSX in tow can make for a more intuitive component. Keep reading to find out why?

注意:我并不是说没有JSX来解决上述问题不是简单的方法,我只是说,将这个逻辑转移到JSX拖曳到render()方法上可以使操作更直观零件。 继续阅读以找出原因?

Every component we create in Vue has a render method. This is where Vue chooses to render the component. Even if we don't define this method, Vue will do it for us.

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

This means that when we define HTML templates in Vue — Vue's template compiler compiles it to a createElement function that takes a couple parameters and returns the result from the render function.

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

To fix the code in the previous section, we remove the template property or the template tag and define a render() method on the component. If the render method is defined on a component, Vue will ignore the template definition.

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

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

The above code does a few things:

上面的代码做了几件事:

  1. The render method takes a createElement helper from Vue.

    render方法使用Vue的createElement帮助器。
  2. We programmatically define our tag.

    我们以编程方式定义标签。
  3. Then we create the tag and pass its attributes, classes etc as an object. There are quite a few options we can pass to createElement.

    然后,我们创建标签并将其属性,类等作为对象传递。 我们可以传递给createElement 选项很多。
  4. We return the newly created element for rendering.

    我们返回新创建的元素进行渲染。

Note: Every template we define for a Vue component will be converted into a render method that returns a createElement function. It's because of this reason the render method will take precedence over a template definition.

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

Take this example:

举个例子:

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

The template compiler will convert the HTML above into:

模板编译器会将上面HTML转换为:

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

Okay! now you might ask this question, "Isn't this bad for readability?" The answer is yes. Once you define a component with many levels of elements nesting or has several sibling elements — we run into a new problem. We just sacrificed readability. Like they say, "we've moved from the frying pan to fire."

好的! 现在您可能会问这个问题:“对可读性来说这不好吗?” 答案是肯定的。 一旦定义了具有许多元素嵌套级别或具有多个同级元素的组件,我们就会遇到一个新问题。 我们只是牺牲了可读性。 就像他们说的那样:“我们已经从煎锅搬到了火上。”

Cue JSX. This is where we'll have JSX bring back the readability we lost.

提示JSX。 这是我们让JSX恢复丢失的可读性的地方。

什么是JSX ( What is JSX )

If you already know about JSX, feel free to skip to the next section where I'll show you how to use JSX in Vue.

如果您已经了解JSX,请随时跳到下一节,我将向您展示如何在Vue中使用JSX。

JSX is a term coined by Facebook's engineering team.

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

JSX is an XML-like syntax extension to JavaScript without any defined semantics.

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

JSX is NOT intended to be implemented by engines or browsers. Instead, we'll use transpilers like Babel to convert JSX to regular JavaScript.

JSX不能由引擎或浏览器实现。 相反,我们将使用像transpilers 巴贝尔以JSX转化为常规JavaScript。

// this line below is an example of JSX
 const heading = <h1>Welcome to Scotch</h1>;

Basically, JSX lets us use an HTML-like syntax in JavaScript.

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

Unfortunately, this article assumes you already know JSX, so teaching JSX is beyond the scope of this article. I'll still point you in the right direction. JSX is very easy to grok and can be done in a couple minutes.

不幸的是,本文假设您已经了解JSX,因此教授JSX不在本文讨论范围之内。 我仍然会指出正确的方向。 JSX非常容易掌握,可以在几分钟内完成。

Use these links to learn The basics of JSX, Learn JSX in-depth, finally, if you really want to know about the specification that is JSX, visit its official website.

使用这些链接来学习JSX的基础知识 ,最后, 深入学习JSX ,如果您真的想了解JSX的规范,请访问其官方网站 。

配置Vue以使用JSX ( Configure Vue to use JSX )

If you use Vue-cli greater or equal to version 3.0 you are in luck as JSX is supported.

如果您使用大于或等于3.0版的Vue-cli ,那么您会很幸运,因为它支持JSX。

If you are using an older version of Vue-cli that doesn't support JSX, you can add it by installing babel-preset-vue-app and add it to your .babelrc file.

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

To install:

安装:

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

# Using yarn
 yarn add --dev babel-preset-vue-app

In you .babelrc file, all you have to do is:

在您的.babelrc文件中,您要做的就是:

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

There, we can now use JSX in our component's render function.

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

Vue的JSX语法陷阱 ( Vue's JSX syntax gotchas )

There are few gotchas to using JSX in Vue.

在Vue中使用JSX的陷阱很少。

First, you can no longer use the : and @ shortcuts for binding and listening to events. They are invalid JSX syntax and your code won't compile.

首先,您不再可以使用:@快捷方式来绑定和监听事件。 它们是无效的JSX语法,因此您的代码无法编译。

To listen for events in JSX, we need the "on" prefix. For example, use onClick for click events.

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

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

To modify events, use:

要修改事件,请使用:

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

To bind a variable, instead of : use:

要绑定一个变量,而不是:使用:

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

To set HTML string as the content of an element, instead of v-html use:

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

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

We can also spread a large object.

我们还可以散布一个大物体。

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

在渲染中使用JSX ( Using JSX in render )

Going back to our initial "TextField" component. Now that we have JSX enabled in our Vue app, we can now do this.

回到我们最初的“ 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 JSX组件 ( Importing Vue JSX Components )

Another benefit to using JSX in Vue is that we no longer have to register every component we need. We just import and use.

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

import {Button} from '../components'

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

如何使JSX与TypeScript一起使用 ( How to make JSX work with TypeScript )

TypeScript is used as a mechanism that adds type-checking to JavaScript. You can read more.

TypeScript用作一种向JavaScript添加类型检查的机制。 您可以阅读更多内容 。

To add JSX support to TypeScript all we need to do is modify our tsconfig.json.

要将JSX支持添加到TypeScript,我们要做的就是修改tsconfig.json

To enable JSX in TypeScript, first save the file as a .tsx file and modify your tsconfig.json to include:

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

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

Setting the jsx option to "preserve" means that TypeScript should not process the JSX. Doing this lets Babel take control of everything JSX and TypeScript stick to types as it does not yet support Vue JSX. You can learn more.

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

Then create a jsx.d.ts file in your project and add the TypeScript JSX declarations for Vue.

然后在您的项目中创建一个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
     }
   }
 }

Make sure that TypeScript can load the declaration file. Or, you can add autoloading for it in tsconfig.json via:

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

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

结论 ( Conclusion )

That's it for today. Enjoy having some or all of your Vue.js templates in JSX.

今天就这样。 享受在JSX中拥有部分或全部Vue.js模板。

And, please no complaints about JSX breaking SOC (separation of concerns), I can't take another one of those arguments. If you prefer using the createElement function with objects by all means enjoy!!

而且,请不要抱怨JSX破坏了SOC(关注点分离),我不能接受其中一个论点。 如果您更喜欢将createElement函数与对象一起使用,那就createElement了!!

Let me know your thoughts and suggestions in the comments.

在评论中让我知道您的想法和建议。

Cheers!

干杯!

翻译自: https://scotch.io/tutorials/using-jsx-with-vue-and-why-you-should-care

vue vue-jsx标签

更多推荐

vue vue-jsx标签_将JSX与Vue一起使用以及为什么要关心