【JS】What is jsx/tsx? Why are Vue3's component libraries using jsx/tsx? How to use jsx/tsx in Vue3?

A few days ago, I got a question, why does React use JSX syntax, which makes the code seem "very coupled". According to tradition, it is recommended to separate html, js, and css templates. Where is the superiority of this design?

1. What is jsx?

JSX , the abbreviation of javascript Xml, is a syntactic sugar provided by Facebook's open source React framework, which can use HTML language in JS.

Official website original text:

JSX is an XML-like syntax extension to ECMAScript without any defined semantics. It’s NOT intended to be implemented by engines or browsers. It’s NOT a proposal to incorporate JSX into the ECMAScript spec itself. It’s intended to be used by various preprocessors (transpilers) to transform these tokens into standard ECMAScript.

2. Why are some component libraries using jsx/tsx?

For JSX and template(template rendering), it is recommended to templateuse (especially in business scenarios). Vue 3 has done a lot of optimization based on templatethe analysis , and it is transparent to the user, and the compiler has completed all the optimization operations silently. If you JSXuse , you need to manually perform some optimization operations.

For example, why the Vant component library chooses JSX, the main reason is that the component library code is more dynamic than the business code, and using JSX can flexibly control dynamic DOM fragments.

For example, suppose there is a scene where it is propsnecessary reverseto decide whether to swap the rendering order of two pieces of content based on the property on the .

This can be easily achieved in JSX:

const renderContent = () => {
    
    
  const Content = [
    <div class="foo">Foo DOM...</div>,
    <div class="bar">Bar DOM...</div>,
  ];
  if (props.reverse) {
    
    
    Content.reverse();
  }
  return <div>{
    
    Content}</div>;
}

If implemented through templates, without abstracting subcomponents, the template structure of foo and bar needs to be written twice to meet this requirement:

<template>
  <div>
    <template v-if="reverse">
      <div class="bar">Bar DOM...</div>
      <div class="foo">Foo DOM...</div>
    </template>
    <template v-else>
      <div class="foo">Foo DOM...</div>
      <div class="bar">Bar DOM...</div>
    </template>
  </div>
</template>

Therefore, in highly dynamic scenarios, JSX will have certain advantages.

In general:

Composition API + templateis the most cost-effective option.

Composition API + JSXIt is the ultimate choice in some scenarios, and correspondingly more development costs are required. JSX excels in flexibility, and in some situations with high dynamic requirements, JSX has become the standard configuration.

3. Get started quickly with jsx/tsx

In JSX expressions, 小括号 ( )wrapping JSXcode is used 大括号 { }to embed dynamic values. For usage in vue, see: rendering function & JSX

Vue's type definitions also provide type inference support for TSX syntax. When using TSX syntax, make sure to configure it tsconfig.jsonin "jsx": "preserve"so that TypeScript can guarantee the integrity of the Vue JSX syntax compilation process.

v-if

  • Only v-showinstructions , there are no v-ifinstructions
  • Both can be achieved using if/elseand ternary expressions

template:

<div>
  <div v-if="ok">yes</div>
  <span v-else>no</span>
</div>

jsx:

<div>
	{ok.value ? <div>yes</div> : <span>no</span>}
</div>

vue3 example:

setup() {
    
    
    const isShow = false
    const element = () => {
    
    
        if (isShow) {
    
    
            return <span>我是if</span>
        } else {
    
    
            return <span>我是else</span>
        }
    }
    return () => (
        <div>
            <span v-show={
    
    isShow}>我是v-show</span>
            {
    
    
                element()
            }
            {
    
    
                isShow ? <p>我是三目1</p> : <p>我是三目2</p>
            }
        <div>
    )
}

v-for

  • Similarly, there is no v-forinstruction , we only need mapto use the array method of Js to render the list

template:

<ul>
  <li v-for="{ id, text } in items" :key="id">
    {
   
   { text }}
  </li>
</ul>

jsx:

<ul>
  {
  	items.value.map(({ id, text }) => {
	    return <li key={id}>{text}</li>
	  })
  }
</ul>

vue3 example:

setup() {
    
    
   const listData = [
       {
    
    name: 'Tom', age: 18},
       {
    
    name: 'Jim', age: 20},
       {
    
    name: 'Lucy', age: 16}
   ]
   return () => (
       <div>
           <div class={
    
    'box'}>
               <span>姓名</span>
               <span>年龄</span>
           </div>
           {
    
    
               prop.listData.map(item => {
    
    
                   return <div class={
    
    'box'}>
                       <span>{
    
    item.name}</span>
                       <span>{
    
    item.age}</span>
                   </div>
               })
           }
       </div>
   )
}

v-on

Those onstarting and followed by uppercase letters propsare considered event listeners. For example, equivalentonClick to in the template .@click

<button
  onClick={(event) => {
    /* ... */
  }}
>
  click me
</button>

event modifier

For the .passive, .captureand .onceevent modifiers, you can use camel case to splice them after the event name:

<input
  onClickCapture={() => {}}
  onKeyupOnce={() => {}}
  onMouseoverOnceCapture={() => {}}
/>

class and style binding

There are two ways to bind class class names, using template strings or using arrays.

// 使用模板字符串两个类名之间使用空格隔开
<div className={
    
    `header ${
      
       isBg ? 'headerBg' : '' }`}>header</div>
//数组
<div class={
    
     [ 'header', isBg && 'headerBg' ] } >header</div>

// style绑定需要使用 双大括号
const color = 'red'
const element = <sapn style={
    
    {
    
     color, fontSize: '16px' }}>style</sapn>

4. Examples of use

In development, you will encounter such a requirement: get the reference of the subcomponent and call the method defined in the subcomponent.

If a form component is encapsulated, the reference of this form component needs to be called in the parent component, and the validation form function or reset form function of this form component needs to be called. To achieve this function, first expose the function that the parent component needs to call in the child component, then go to the parent component to obtain the reference of the child component, and finally call the method exposed by the child component through the reference of the child component.

1. Subcomponent exposure method

SFC (.vue) exposed method

In the component defined by .vue, defineExpose() the method , which can expose the internal method of the component to the parent component.

Create subcomponent demo-component-sfc.vue:

<template>
  <el-button type="primary" @click="demoFun('child')">demo component sfc</el-button>
</template>
<script lang="ts" setup name="demo-component-sfc">
	const demoFun = (str: string) => {
      
      
	  console.log('demo component sfc', str)
	}
	// 使用 defineExpose 暴露组件内部的方法
	defineExpose({
      
       demoFun })
</script>

TSX (.tsx) exposure method

Components defined in .tsx mode also expose component content through the expose() method in the parameter context.

Create subcomponent demo-component-tsx.tsx:

import {
    
     defineComponent } from 'vue'
export default defineComponent({
    
    
  name: 'demo-component-tsx',
  setup (props, context) {
    
    
    const demoFun = (str: string) => {
    
    
      console.log('demo component tsx', str)
    }
    // 使用 expose 暴露组件内部的方法
    context.expose({
    
     demoFun })
    return () => (
      <el-button type="primary" onClick={
    
    () => demoFun('child')}>demo component tsx</el-button>
    )
  }
})

2. The parent component calls the method in the child component

To obtain a reference to a component in .tsx, first define a ref variable, and then set the variable to the ref attribute of the child component.

import {
    
     defineComponent, ref } from 'vue'
import DemoComponentSfc from '@/components/ref/demo-component-sfc.vue'
import DemoComponentTsx from '@/components/ref/demo-component-tsx'
export default defineComponent({
    
    
  name: 'demo-ref-tsx',
  setup () {
    
    
    const sfcRef = ref()
    const onBtnClick1 = () => {
    
    
      if (sfcRef.value) {
    
    
        sfcRef.value && sfcRef.value.demoFun('parent')
      }
    }
    const tsxRef = ref()
    const onBtnClick2 = () => {
    
    
      if (tsxRef.value) {
    
    
        tsxRef.value && tsxRef.value.demoFun('parent')
      }
    }
    return () => (
      <>
        <div>
          <DemoComponentSfc ref={
    
    sfcRef} />
          <el-button onClick={
    
    onBtnClick1}>parent button</el-button>
        </div>
        <div style="margin-top: 10px;">
          <DemoComponentTsx ref={
    
    tsxRef} />
          <el-button onClick={
    
    onBtnClick2}>parent button</el-button>
        </div>
      </>
    )
  }
})

Remarks: <></>In this way, the browser renders html without elements, saving a box position.

https://juejin.cn/post/7151950058501373989
Jinitaimei

おすすめ

転載: blog.csdn.net/weixin_42960907/article/details/129427293