vue之jsx

发布时间 2023-08-03 20:02:02作者: 这样就好了

一. vue中的jsx

用接近模板的语法代替render函数
不仅能自由地渲染dom,同时语法上也和template相似

例如:

  • "标签 h+ 变量"可以生成不同类型的级别的标题
  • 使用html字符串渲染
    Message.alert({
    messge:
    确定要删除xxx的笔记?
    ,
    type: 'warning'
    })
  • 使用函数组件,它只是一个接受一些 prop 的函数
    应用: 程序化地在多个组件中选择一个来代为渲染
// 一个文件写多个组件
const Input = (props) => <input {...props} />
export const Textarea = (props) => <input {...props} />
export const Password = (props) => <input type="password" {...props} /> 

export default Input

总结: 根据使用场景去用jsx。

二. jsx语法

1. 文本插值

模板内双大括号

<h1>{{ msg }}</h1>

jsx单大括号

const name = 'Vue'
const element = <h1>Hello, { name }</h1>

2. 条件和循环

模板: v-for,v-if
jsx: v-for使用for循环或者array.map代替, v-if使用if-else语句,三元表达式

const element = (name) => { // if要放在函数里面
  if (name) {
    return <h1>Hello, { name }</h1>
  } else {
    return <h1>Hello, Stranger</h1>
  }
}

const element = icon ? <span class="icon"></span> : null

const list = ['java', 'c++', 'javascript', 'c#', 'php']
return (
  <ul>
  {list.map(item => {
   return <li>{item}</li>
  })}
  </ul>
)

3.属性绑定 单括号

在模板代码中,一般通过 v-bind:prop="value"或:prop="value"来给组件绑定属性,在JSX里面就不能继续使用v-bind指令了,而是通过单大括号的形式进行绑定

const href = 'https://xxx.com'
const element = <a href={href}>xxx</a>

此外,模板代码中能通过

批量绑定标签属性。

在JSX中也有相应的替换方案:<div {...properties}>。

class绑定同样也是使用单大括号的形式

const element = <div className={`accordion-item-title ${ disabled ? 'disabled' : '' }`}></div>
const element = <div class={
    [ 'accordion-item-title', disabled && 'disabled' ]
  }
>Item</div>

style绑定需要使用双大括号

const width = '100px'
const element = <button style={{ width, fontSize: '16px' }}></button>

4. 事件绑定

(1)在模板代码中通过v-on指令监听事件,在JSX中通过on + 事件名称的大驼峰写法来监听,且绑定事件也是用大括号,比如click事件要写成onClick/ vOn:click,mouseenter事件要写成onMouseenter

const confirm = () => {
  // 确认提交
}
<button onClick={confirm}>确定</button>

(2).native修饰符: 将前面的on替换为nativeOn, 即onClick变成nativeOnClick。

 render() {
    // 监听下拉框根元素的click事件
    return <CustomSelect nativeOnClick={this.handleClick}></CustomSelect>
  }

(3) 除了上面的监听事件的方式之外,我们还可以使用对象的方式去监听事件

  render() {
    return (
      <ElInput
        value={this.content}
        on={{
          focus: this.handleFocus,
          input: this.handleInput
        }}
        nativeOn={{
          click: this.handleClick
        }}
      ></ElInput>
    )
  }

(4)对于 .passive、.capture 和 .once 这些事件修饰符,Vue 提供了相应的前缀可以用于 on

on: {  
    '!click': this.doThisInCapturingMode,  // capture
    '~keyup': this.doThisOnce,  // .once
    '~!mouseover': this.doThisOnceInCapturingMode  // .capture.oncee 或.once.capture 
}

其他修饰符可以使用事件方法

5. v-show与v-model

大多数指令并不能在JSX中使用,对于原生指令,只有v-show是支持的。

而v-model是Vue提供的一个语法糖,它本质上是由 value属性(默认) + input事件(默认)组成的,所以,在JSX中,我们便可以回归本质,通过传递value属性并监听input事件来手动实现数据的双向绑定(现在用vModel也可以实现)

export default {
  data() {
    return {
      name: ''
    }
  },
  methods: {
    // 监听 onInput 事件进行赋值操作
    handleInput(e) {
      this.name = e.target.value
    }
  },
  render() {
    // 传递 value 属性 并监听 onInput事件
    return <input value={this.name} onInput={this.handleInput}></input>
  }
}

此外,在脚手架vue-cli4中,已经默认集成了对v-model的支持,可以直接使用

<input v-model={this.value}>

同样的,在JSX中,对于.sync也需要用属性+事件来实现,如下代码所示:

export default {
  methods: {
    handleChangeVisible(value) {
      this.visible = value
    }
  },
  render() {
    return (
      <ElDialog
        title="测试.sync"
        visible={this.visible}
        on={{ 'update:visible': this.handleChangeVisible }}
      ></ElDialog>
    )
  }
}

6.插槽

(1) 默认插槽

在模板template中

// 自定义组件 myComponent
<div class="my-component">
 <slot></slot> 
</div>

在Vue的实例this上面有一个属性$slots,这个上面就挂载了一个这个组件内部的所有插槽,使用this.$slots.default就可以将默认插槽加入到组件内部

<div class="my-component">
 { this.$slots.default }
</div>

(2) 具名插槽

有时我们需要多个插槽, 就需要为插槽命名
模板template自定义具名插槽:

// 自定义组件 myComponent
<div class="container">
  <header>
    <slot name="header"></slot>
  </header>
</div>
// 使用
<myComponent>
  <h1 slot="header">标题</h1>
</myComponent>

jsx自定义具名插槽:这里定义一个叫footer的具名插槽

// 自定义组件 myComponent
render() {
  return (
    <div class="container">
    <header>
        { this.$slots.footer }
    </header>
    </div>
  )
}
// jsx使用方式
render () {
  return (
    <myComponent>
      <h1 slot="footer">底部</h1>
    </myComponent>
  )
}

(3) 作用域插槽

让插槽内容能够访问子组件中才有的数据

模板template中的使用

// 自定义组件 myComponent
<div class="container">
    <header>
        <slot name="default" :data="data" >
    </header>
</div>

// 使用
<myComponent>
  <template  #default="slotProps">
    <div>{{ slotProps.data }} </div>
  </template>
</myComponent>

jsx的作用域插槽写法,

// 自定义组件 myComponent
props: ['data'],
render () {
  return (
    <div class="container">
      <header>
          { 
            this.$scopedSlots.default({
              text: this.data
            })
          }
      </header>
    </div>
  )
}
// 使用
render () {
  const scopedSlots = {
      default: ({ text }) => {
        return <div style="color:red;">{text + '333333'}</div>
      }
  }
  return (
    <myComponent scopedSlots={scopedSlots}></myComponent>
  )
}

7. 使用自定义组件

import MyComponent from './my-component'
 
export default {
  render() {
    return <MyComponent>hello</MyComponent>
  },
}

8.在method里返回JSX

 methods: {
    renderFooter() {
      return (
        <div>
          <ElButton>确定</ElButton>
          <ElButton>取消</ElButton>
        </div>
      )
    }
  },
  render() {
    const buttons = this.renderFooter()
    return (
      <ElDialog visible={this.visible}>
        <div>内容</div>
        <template slot="footer">{buttons}</template>
      </ElDialog>
    )
  }

参考:https://blog.csdn.net/qq_41581588/article/details/129183261