vue3 JSX 从零开始

8,450 阅读4分钟

前置准备

初始化项目

  • 使用vuecli初始化项目时有人喜欢使用 vue ui 有人喜欢使用命令行,vue-ui更直观一些。
  • 打开命令行工具输入vue ui

image.png

  • 打开项目管理器

image.png

  • 选择创建 - 点击下方创建按钮

image.png

  • 创建项目 - 一目了然

image.png

  • 选择配置

image.png

image.png

image.png

  • 最后点击创建
  • 但是这里并没有结束 仍需要安装一个插件babel-plugin-jsx
// 安装插件
npm install @vue/babel-plugin-jsx -D

// 配置 Babel
{
  "plugins": ["@vue/babel-plugin-jsx"]
}

image.png

  • 需要注意的是 创建的时候选择了 1. 代码检查 2. 代码提交检查 如不需要可以关闭。

配置 element-plus

  • 这个其实没啥说的,直接跟着官网走就行 不过是个基础 还是略微说一点。
// 在main.js
import { createApp } from 'vue'
import App from './App.vue';

import ElementPlus from 'element-plus';
import 'element-plus/lib/theme-chalk/index.css';
// 引入中文语言包
import zhCn from 'element-plus/lib/locale/lang/zh-cn'

const app = createApp(App)
app.use(ElementPlus,{ locale: zhCn })
app.mount('#app')
  • 或者这样?
// 新建ElementPlus.js 文件
import ElementPlus from 'element-plus'
import 'element-plus/lib/theme-chalk/index.css'
import zhCn from 'element-plus/lib/locale/lang/zh-cn'

export default (app) => {
  app.use(ElementPlus, { locale: zhCn })
}

// 使用 在main.js 引入 ElementPlus.js
import installElementPlus from './plugins/ElementPlus.js'
const app = createApp(App)
// 传入app
installElementPlus(app)
app.mount('#app')

jsx 知识 (与element-plus结合使用)

css

// 行内样式
<div style={{ fontSize: '18px', fontWeight: 'bold', marginBottom: '18px' }}>{pageName.value}</div>
 
// class 引入相关css 文件
<div class='menuBox'></div>

指令

v-show

import { defineComponent, ref } from 'vue'

const cs = defineComponent({
  setup () {
    const isShow = ref(true)
    const isShowClick = () => {
      isShow.value = !isShow.value
    }
    return () => (
      <div>
        <el-button onClick={isShowClick}>显示隐藏</el-button>
        <p v-show={isShow.value}>11111111111111111</p>
      </div>
    )
  }
})

export default cs

v-for 和 v-if

  • jsx 中的 v-for 与v-if 可以通过计算的形式来实现 如下图官网所说

截屏2021-08-07 下午7.33.38.png

  • 在jsx中是这样 v-if 同理 在循环中通过判断过滤掉不需要的数据。
const datItemList = listOfDatesOfTheMonth.map(item => {
  return <div class="dateItem">{item.date}</div>
})

<div class="dateItemBox">{datItemList}</div>

v-model or v-models

  • 先来看一下 v-model 的官方示例 图好像有点糊🤦‍♂️

image.png

// 拷贝下官方示例 😁
// v-model={val} 绑定了 val 在组件中使用   props: { modelValue: Number } 接收
// 需要注意的是 绑定的val如果是 ref创建的 val 需要替换为 val.value
// <input v-model={val.value} />
<input v-model={val} />


//  modifier 绑定修饰符 不理解的可以参照官方文档 
<input v-model={[val, ["modifier"]]} />

// argument 更改v-model 默认绑定props.modelValue 为 props.argument
<A v-model={[val, "argument", ["modifier"]]} />
  • 理解了v-modelv-models 好像也差不多,不过是吧 v-model的一维数组 改为二位数组,也算是符合直觉。

image.png

自定义指令

  • 这个其实与sfc的书写方式基本一样,可以参照官网文档来实现

slot 插槽定义

  • jsx 的 slot 定义与 sfc 的差异巨大,一个是函数调用,一个是定义属性
  • jsx 定义 slot
import { defineComponent } from 'vue'

const st = defineComponent({
  // setup 函数默认接收两个参数 1. props 2. ctx 上下文 其中包含 slots、attrs、emit 等
  // 从ctx 解构出 slots
  setup (props, { slots }) {
    return () => (
      <div>
        {}
        { slots.default()/* 默认插槽 */ },
        { slots.title() /* title 具名插槽 */}
      </div>
    )
  }
})
export default st
  • sfc 的插槽定义
<template>
  <div>
    <!-- 默认插槽   -->
    <slot></slot>
    <!-- 具名 title 插槽   -->
    <slot name="title"></slot>
  </div>
</template>

slot 插槽使用

  • vue3.0 的jsx 中 插槽是由 v-slots 定义在引用组件上的。如element-plus 的menu组件
<el-submenu index='/cs/sys' v-slots={{
      title: () => (
        <div>
          <i class='el-icon-setting'></i>
          <span>系统管理</span>
        </div>)
    }}>
  <el-menu-item index='/cs/sys/user'>用户管理</el-menu-item>
</el-submenu>
  • title 就是组件预留的插槽
  • 再来看一下sfc template 的定义
<el-menu-item index="/home">
    <i class="iconfont icon-shouye"></i>
    <span slot="title">首页</span>
</el-menu-item>
  • 区别还是很明显的 sfc 的 slot 是需要在使用组件的内部定义一个承载元素来使用。而 jsx 则是直接在组件上使用v-slots来定义。
  • 关于默认插槽 jsx 是声明一个default函数,sfc则是直接写在引用组件的内部如<div-slot>这里的内容会被渲染到默认插槽,前提是组件定义了默认插槽</div-slot> image.png

emit事件

  • vue jsx emit自定义事件触发前边加onelement-plus 分页组件的 size-change pageSize 函数 改变时会触发
<el-pagination
    background
    onSizeChange={sizeChange}
    layout="total, sizes, , jumper, prev, pager, next"
    total={tableData.length}>
</el-pagination>
  • onSizeChange={sizeChange} 这样写会触发
  • onSize-change={sizeChange} 这样写也会触发
  • on-size-change={sizeChange} 这样写不行
  • onsizechange={sizeChange} 当然这样也不行

总结

  • 多看文档,vue的相关文档一直都很友好。但是一定要耐心看。
  • 仓库地址
  • 如有错误 烦请指正 多多包含!