1、setup
vue3.0结构:
  
   - 
    
     
    
    
     
      import { 
      PropType } 
      from 
      'vue' 或者 
      '@vue/composition-api'
     
    
- 
    
     
    
    
     
      export 
      default 
      defineComponent({
     
    
- 
    
     
    
    
         
      props: {
     
    
- 
    
     
    
    
             
      age: {
     
    
- 
    
     
    
    
                 
      type: 
      Number
     
    
- 
    
     
    
    
     
              },
     
    
- 
    
     
    
    
             
      onToggleClick: {
     
    
- 
    
     
    
    
                 
      type: 
      Function 
      as 
      PropType<
      () => 
      void>
     
    
- 
    
     
    
    
     
              }
     
    
- 
    
     
    
    
     
          }
     
    
- 
    
     
    
    
         
      setup(
      props, {slots, emit, expose, attrs, listeners, root}) {
     
    
- 
    
     
    
    
             
      // slots 插槽使用在下面第6类中介绍
     
    
- 
    
     
    
    
             
      // emit('xxx', xxx)
     
    
- 
    
     
    
    
             
      // expose 有可能是被废弃,当你使用内核为'@vue/composition-api'时是肯定被废弃的
     
    
- 
    
     
    
    
             
      // attrs 跟vue2的 this.$attrs类似
     
    
- 
    
     
    
    
             
      // listeners 跟vue2的 this.$listeners 类似
     
    
- 
    
     
    
    
             
      // root vue实例
     
    
- 
    
     
    
    
             
      // 其他的还有一些,比如 parent, children
     
    
- 
    
     
    
    
     
          }
     
    
- 
    
     
    
    
     
      })
     
    
 vue3.2
  
   - 
    
     
    
    
     
      <script lang=
      "ts" setup>
     
    
- 
    
     
    
    
         
      // emit用法 先定义emit,执行时候和vue3.0方式一样
     
    
- 
    
     
    
    
         
      const emit = defineEmits<{
     
    
- 
    
     
    
    
     
              (
      e: 
      'clickBtn', 
      data: 
      any): 
      void
     
    
- 
    
     
    
    
     
            }>()
     
    
- 
    
     
    
    
         
      // props用法
     
    
- 
    
     
    
    
         
      interface 
      Props {
     
    
- 
    
     
    
    
     
            labelWidth?: 
      string | 
      number 
      //标签的宽度
     
    
- 
    
     
    
    
     
          }
     
    
- 
    
     
    
    
         
      const props = 
      withDefaults(defineProps<
      Props>(), {
     
    
- 
    
     
    
    
             
      labelWidth: 
      '120px'
     
    
- 
    
     
    
    
     
          })
     
    
- 
    
     
    
    
         
      // 父组件想要调用子组件方法,首先在子组件将方法名抛出去
     
    
- 
    
     
    
    
         
      defineExpose({ getFormValue })
     
    
- 
    
     
    
    
     
      <script>
     
    
 2、ref,reactive,toRef,toRefs
重点:
ref:
ref本质也是reactive,ref(obj)等价于reactive({value: obj})
- 在vue中使用ref的值,不用通过.value获取
- 在js中使用ref的值,必须通过.value获取
reactive:
- reactive的参数必须是一个对象,包括json数据和数组都可以,否则不具有响应式
toRef,toRefs:
常用于解构props,保持响应式特征
区别是toRef只能转换一个值,toRefs转换所有值
3、watch
3.1、监听基础类型
  
   - 
    
     
    
    
       
      const nums = 
      ref(
      0)
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
       
      watch(nums, 
      (newValue, oldValue) => {
     
    
- 
    
     
    
    
     
        })
     
    
3.2、监听对象
  
   - 
    
     
    
    
     
      const react = 
      reactive({
     
    
- 
    
     
    
    
     	
      name: 
      'xxx',
     
    
- 
    
     
    
    
         
      prop: {
     
    
- 
    
     
    
    
             
      xxx: xxx
     
    
- 
    
     
    
    
     
          }
     
    
- 
    
     
    
    
     
      })
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
     
      // 监听整个对象
     
    
- 
    
     
    
    
     
      watch(react, 
      (newValue, oldValue) => {
     
    
- 
    
     
    
    
     
      })
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
     
      // 监听对象某个属性(最常用)
     
    
- 
    
     
    
    
     
      watch(
      () => react.
      name, 
      (newValue, oldValue) => {
     
    
- 
    
     
    
    
     
      })
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
     
      // 监听对象的第一级子属性
     
    
- 
    
     
    
    
     
      watch(
      () => ({ ...react }), 
      (newValue, oldValue) => {
     
    
- 
    
     
    
    
     
      })
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
     
      // 监听对象的所有属性(最常用)
     
    
- 
    
     
    
    
     
      watch(
      () => react, 
      (newValue, oldValue) => {
     
    
- 
    
     
    
    
     
      }, { 
      deep: 
      true })
     
    
 3.3、监听数组
ref定义的数组,下面这种写法是完全没有问题的,新旧数据都是正确的
  
   - 
    
     
    
    
     
      const react = 
      ref([])
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
     
      // 监听整个数组 
     
    
- 
    
     
    
    
     
      watch(
      () => [...react.
      value], 
      (newValue, oldValue) => {
     
    
- 
    
     
    
    
     
      })
     
    
- 
    
     
    
    
      
     
    
reactive定义的数组,不管怎么样,新数据是正确的,旧数据和新数据一直都是一致,这就有问题le, 所以解决方式就只有将数组嵌套再对象里面,然后监听数组的长度
  
   - 
    
     
    
    
     
      const react = 
      reactive([])
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
     
      // 新数据正确,旧数据有问题
     
    
- 
    
     
    
    
     
      watch(react, 
      (newValue, oldValue) => {
     
    
- 
    
     
    
    
     
      })
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
     
      // 新数据正确,旧数据有问题
     
    
- 
    
     
    
    
     
      watch(react, 
      (newValue, oldValue) => {
     
    
- 
    
     
    
    
     
      }, {
      deep: 
      true})
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
     
      // 不管加不加deep,都无法运行
     
    
- 
    
     
    
    
     
      watch(
      () => react.
      length, 
      (newValue, oldValue) => {
     
    
- 
    
     
    
    
     
      })
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
     
      const react = 
      reactive({
     
    
- 
    
     
    
    
         
      arr: []
     
    
- 
    
     
    
    
     
      })
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
     
      // 新旧数据正确
     
    
- 
    
     
    
    
     
      watch(
      () => react.
      arr.
      length, 
      (newValue, oldValue) => {
     
    
- 
    
     
    
    
     
      })
     
    
 3.4、watchEffect
其实和watch的区别,我的理解哈,watchEffect类似于immediat为true,开局立即启动了,将watchEffect赋值给一个变量,再调用的话,就是解除监听了,这一点要看你喜欢用watch还是watchEffect,当然那些副作用啥的概念我也没去研究,就暂时不讲解那些了
  
   - 
    
     
    
    
     
      // 监听 
     
    
- 
    
     
    
    
     
      const handle = 
      watchEffect(
      () => {
     
    
- 
    
     
    
    
         
      /* ... */
     
    
- 
    
     
    
    
     
        })
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
     
      // 解除监听
     
    
- 
    
     
    
    
     
      handle()
     
    
4、computed
其实就和vue2的computed类似
  
   - 
    
     
    
    
     
      const xxx = 
      ref(
      0)
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
     
      // 只get
     
    
- 
    
     
    
    
     
      computed(
      () => xxx.
      value)
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
     
      // set get
     
    
- 
    
     
    
    
     
      computed({
     
    
- 
    
     
    
    
         
      set(
      val) {
     
    
- 
    
     
    
    
     
          },
     
    
- 
    
     
    
    
         
      get(
      ) {
     
    
- 
    
     
    
    
     
          }
     
    
- 
    
     
    
    
     
      })
     
    
5、css
当然我建议将css提出来,这样tsx里面就只有逻辑层和渲染层了,再很一点的话,将逻辑层也提出来,用一个单独的ts文件存放,tsx就只放渲染层的代码
  
   - 
    
     
    
    
     
      css文件名: index.
      module.
      scss
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
     
      方式一:直接
      import的话,就是用的全局样式
     
    
- 
    
     
    
    
     
      index.
      module.
      scss:
     
    
- 
    
     
    
    
     
      :
      global{
     
    
- 
    
     
    
    
     
          .
      top-container{
     
    
- 
    
     
    
    
             
      width: 100px;
     
    
- 
    
     
    
    
     
          }
     
    
- 
    
     
    
    
     
      }
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
     
      import 
      'index.module.scss';
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
     
      export 
      default 
      defineComponent({
     
    
- 
    
     
    
    
         
      return 
      () => (
     
    
- 
    
     
    
    
             
      <div class='top-container'></div>
     
    
- 
    
     
    
    
     
          )
     
    
- 
    
     
    
    
     
      })
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
     
      方式二:
      import 
      Styles 
      from 
      'index.module.scss' 的话,就是组件scoped方式,不过里面样式要写成小驼峰形式(建议使用)
     
    
- 
    
     
    
    
     
      index.
      module.
      scss:
     
    
- 
    
     
    
    
     
      .
      topContainer{
     
    
- 
    
     
    
    
         
      width: 100px;
     
    
- 
    
     
    
    
     
      }
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
     
      import 
      Styles 
      from 
      'index.module.scss';
     
    
- 
    
     
    
    
     
      export 
      default 
      defineComponent({
     
    
- 
    
     
    
    
         
      return 
      () => (
     
    
- 
    
     
    
    
             
      <div class={styles.topContainer}></div>
     
    
- 
    
     
    
    
     
          )
     
    
- 
    
     
    
    
     
      })
     
    
 6、tsx
6.1、花括号和小括号使用
花括号一般用于js逻辑处理的时候和属性、事件赋值时候,类似于插值表达式(主要是逻辑层处理)
  
   - 
    
     
    
    
                
     
    
- 
    
     
    
    
     
      export 
      default 
      defineComponent({
     
    
- 
    
     
    
    
         
      return 
      () => (
     
    
- 
    
     
    
    
             
      <div>
     
    
- 
    
     
    
    
     
                  {
     
    
- 
    
     
    
    
     
                    showLogo.value && 
      <Logo collapse={isCollapse.value} />
     
    
- 
    
     
    
    
     
                  }
     
    
- 
    
     
    
    
             
      </div>
     
    
- 
    
     
    
    
     
          )
     
    
- 
    
     
    
    
     
      })
     
    
小括号一般用于最外层 包裹组件的时候 或者 包裹一段单独的逻辑时候(主要是渲染层处理)
  
   - 
    
     
    
    
     
      export 
      default 
      defineComponent({
     
    
- 
    
     
    
    
         
      return 
      () => (
     
    
- 
    
     
    
    
             
      <div></div>
     
    
- 
    
     
    
    
     
          )
     
    
- 
    
     
    
    
     
      })
     
    
6.2、事件绑定
tsx目前还没有事件修饰符的写法,所以想要加修饰符,就两种方式
1、使用 @vue/babel-preset-jsx 依赖的时候,使用 vOn:click_stop 类似的方式
2、自行实现修饰符的功能,比如最简单的两个
.prevent, 写的时候就是 e,preventDefault()
.stop 写的时候就是e.stopPropagation()
但是当常规开发时, 使用 短横线或者小驼峰形式都是可以的
  
   - 
    
     
    
    
     
      export 
      default 
      defineComponent({
     
    
- 
    
     
    
    
         
      return 
      () => (
     
    
- 
    
     
    
    
             
      <div>
     
    
- 
    
     
    
    
                 
      <div on-toggle-click={xxx}>
      </div>
     
    
- 
    
     
    
    
                 
      <div onToggleClick={xxx}>
      </div>
     
    
- 
    
     
    
    
             
      </div>
     
    
- 
    
     
    
    
     
          )
     
    
- 
    
     
    
    
     
      })
     
    
6.3、动态class,动态style
class:下面是主流的几种class写法
举个例子:class.headerSearch的classModule 是 模块化class写法定义变量,一般的话你可以不用管它,直接类似下面第3,4,5写法就行了
  
   - 
    
     
    
    
     
      import classModule 
      from 
      './index.module.scss'
     
    
- 
    
     
    
    
     
      export 
      default 
      defineComponent({
     
    
- 
    
     
    
    
         
      return 
      () => (
     
    
- 
    
     
    
    
             
      <div>
     
    
- 
    
     
    
    
                 
      <div class={[classModule.headerSearch, { [classModule.show]: show.value }]>
      </div>
     
    
- 
    
     
    
    
                 
      <div class={[classModule.avatarContainer, classModule.rightMenuItem]}>
      </div>
     
    
- 
    
     
    
    
                 
      <div class='back-to to-top'>
      </div>
     
    
- 
    
     
    
    
                 
      <div class={['back-to', { 'show': show.value }]}>
      </div>
     
    
- 
    
     
    
    
                 
      <div class={[show.value ? 'active' : '', 'tags-view-item']}>
      </div>
     
    
- 
    
     
    
    
             
      </div>
     
    
- 
    
     
    
    
     
          )
     
    
- 
    
     
    
    
     
      })
     
    
style: 下面是主流的几种style写法
  
   - 
    
     
    
    
     
      export 
      default 
      defineComponent({
     
    
- 
    
     
    
    
         
      return 
      () => (
     
    
- 
    
     
    
    
             
      <div>
     
    
- 
    
     
    
    
                 
      <div style={{ 'top': props.buttonTop + 'px', 'background-color': theme.value }}>
      </div>
     
    
- 
    
     
    
    
                 
      <div style={{ display: visible.value ? 'block' : 'none' }}>
      </div>
     
    
- 
    
     
    
    
                 
      <div style='padding: 8px 10px;'>
      </div>
     
    
- 
    
     
    
    
             
      </div>
     
    
- 
    
     
    
    
     
          )
     
    
- 
    
     
    
    
     
      })
     
    
6.4、v-for数组
有童鞋要问了,那我想使用filter筛选怎么办呢? 既然用了tsx,就灵活点呗,tsx里面是允许写逻辑的,直接在里面用filter就可以了
  
   - 
    
     
    
    
                
     
    
- 
    
     
    
    
     
      export 
      default 
      defineComponent({
     
    
- 
    
     
    
    
         
      return 
      () => (
     
    
- 
    
     
    
    
             
      <div>
     
    
- 
    
     
    
    
     
                  {
     
    
- 
    
     
    
    
     
                    array.value.map(route => {
     
    
- 
    
     
    
    
     
                      return 
      <SideBarItem
     
    
- 
    
     
    
    
                       
      item=
      {route}
     
    
- 
    
     
    
    
                       
      basePath=
      {route.path} />
     
    
- 
    
     
    
    
     
                    })
     
    
- 
    
     
    
    
     
                  }
     
    
- 
    
     
    
    
             
      </div>
     
    
- 
    
     
    
    
     
          )
     
    
- 
    
     
    
    
     
      })
     
    
6.5、v-if条件判断
逻辑与运算符:
  
   - 
    
     
    
    
                
     
    
- 
    
     
    
    
     
      export 
      default 
      defineComponent({
     
    
- 
    
     
    
    
         
      return 
      () => (
     
    
- 
    
     
    
    
             
      <div>
     
    
- 
    
     
    
    
     
                  {
     
    
- 
    
     
    
    
     
                    showLogo.value && 
      <Logo collapse={isCollapse.value} />
     
    
- 
    
     
    
    
     
                  }
     
    
- 
    
     
    
    
             
      </div>
     
    
- 
    
     
    
    
     
          )
     
    
- 
    
     
    
    
     
      })
     
    
三目运算符:
  
   - 
    
     
    
    
                
     
    
- 
    
     
    
    
     
      export 
      default 
      defineComponent({
     
    
- 
    
     
    
    
         
      return 
      () => (
     
    
- 
    
     
    
    
             
      <div>
     
    
- 
    
     
    
    
     
                  {
     
    
- 
    
     
    
    
     
                    showLogo.value ? 
      <Logo collapse={isCollapse.value} /> : null
     
    
- 
    
     
    
    
     
                  }
     
    
- 
    
     
    
    
             
      </div>
     
    
- 
    
     
    
    
     
          )
     
    
- 
    
     
    
    
     
      })
     
    
6.6、v-show、v-model
vue3 + tsx 默认支持这两个用法喔~和常规写法一致,不需要像其他tsx转换写法
6.7、slot插槽
下面是vue2关于插槽的讲解链接
下面是vue3 + tsx 关于 插槽的使用方式
scopedSlot:作用域插槽,其意旨在子组件里操作父组件的数据,下面一般都有默认插槽和具名插槽,举个例子: el-table 的使用
  
   - 
    
     
    
    
                
     
    
- 
    
     
    
    
     
      export 
      default 
      defineComponent({
     
    
- 
    
     
    
    
         
      return 
      () => (
     
    
- 
    
     
    
    
             
      <div>
     
    
- 
    
     
    
    
               
      <el-table
     
    
- 
    
     
    
    
                 
      data=
      {errorLogs.value}
     
    
- 
    
     
    
    
                 
      border>
     
    
- 
    
     
    
    
                 
      <el-table-column
     
    
- 
    
     
    
    
                   
      label=
      'Message'
     
    
- 
    
     
    
    
                   
      scopedSlots=
      {{
     
    
- 
    
     
    
    
                     
      default: 
      scope => {
     
    
- 
    
     
    
    
     
                        return (
     
    
- 
    
     
    
    
                         
      <div>
     
    
- 
    
     
    
    
                           
      <div>
     
    
- 
    
     
    
    
                             
      <span class='message-title'>Msg:
      </span>
     
    
- 
    
     
    
    
                             
      <el-tag type='danger'>
     
    
- 
    
     
    
    
     
                                {scope.row.err.message}
     
    
- 
    
     
    
    
                             
      </el-tag>
     
    
- 
    
     
    
    
                           
      </div>
     
    
- 
    
     
    
    
                         
      </div>
     
    
- 
    
     
    
    
     
                        )
     
    
- 
    
     
    
    
     
                      }
     
    
- 
    
     
    
    
     
                    }}
     
    
- 
    
     
    
    
     
                  >
     
    
- 
    
     
    
    
                 
      </el-table-column>
     
    
- 
    
     
    
    
               
      </el-table>
     
    
- 
    
     
    
    
             
      </div>
     
    
- 
    
     
    
    
     
          )
     
    
- 
    
     
    
    
     
      })
     
    
 v-slot:在tsx里应修改为v-slots
child.tsx 子组件
  
   - 
    
     
    
    
               
     
    
- 
    
     
    
    
     
      export 
      default 
      defineComponent({
     
    
- 
    
     
    
    
         
      return 
      () => (
     
    
- 
    
     
    
    
             
      <>
     
    
- 
    
     
    
    
               
      <div>{ slots.header?.() }
      </div>
     
    
- 
    
     
    
    
               
      <div>{ slots.default ? slots.default() : '默认插槽' }
      </div>
     
    
- 
    
     
    
    
             
      </>
     
    
- 
    
     
    
    
     
          )
     
    
- 
    
     
    
    
     
      })
     
    
parent.tsx 父组件
  
   - 
    
     
    
    
               
     
    
- 
    
     
    
    
     
      // 方式一:
     
    
- 
    
     
    
    
     
      export 
      default 
      defineComponent({
     
    
- 
    
     
    
    
         
      setup(
      ) {
     
    
- 
    
     
    
    
             
      const slots = {
     
    
- 
    
     
    
    
               
      header: 
      () => 
      <span>具名插槽喔</span>,
     
    
- 
    
     
    
    
     
              }
     
    
- 
    
     
    
    
         
      return 
      () => (
     
    
- 
    
     
    
    
           
      <child v-slots={slots}>
     
    
- 
    
     
    
    
             
      <div>这才是标题
      </div>
     
    
- 
    
     
    
    
     
            </child >
     
    
- 
    
     
    
    
     
          );
     
    
- 
    
     
    
    
     
        }
     
    
- 
    
     
    
    
     
      })
     
    
  
   - 
    
     
    
    
     
      // 方式二:
     
    
- 
    
     
    
    
     
      export 
      default 
      defineComponent({
     
    
- 
    
     
    
    
         
      setup(
      ) {
     
    
- 
    
     
    
    
         
      return 
      () => (
     
    
- 
    
     
    
    
           
      <child>
     
    
- 
    
     
    
    
     
              {{
     
    
- 
    
     
    
    
     
                default: () => 
      <div>这才是标题
      </div>,
     
    
- 
    
     
    
    
     
                header: () => 
      <span>具名插槽喔
      </span>,
     
    
- 
    
     
    
    
     
              }}
     
    
- 
    
     
    
    
     
            </child >
     
    
- 
    
     
    
    
     
          );
     
    
- 
    
     
    
    
     
        }
     
    
- 
    
     
    
    
     
      })
     
    
7、疑难解答
7.1、vue3 下 tsx 有几种渲染方式?
两种,一种是setup外面 render,一种是setup里面return
render:有this,和antd vue这种组件库写到tsx中,还要再加this,要改的地方比较多(不推荐)
  
   - 
    
     
    
    
     
      import { defineComponent, ref, reactive } 
      from 
      'vue';
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
     
      export 
      default 
      defineComponent({
     
    
- 
    
     
    
    
         
      setup(
      ){
     
    
- 
    
     
    
    
             
      interface 
      Item {
     
    
- 
    
     
    
    
     
                  [
      T: 
      string]: 
      any
     
    
- 
    
     
    
    
     
              }
     
    
- 
    
     
    
    
             
      const num = ref<
      number>(
      0)
     
    
- 
    
     
    
    
             
      const arr = reactive<
      Array<
      Item>>([])
     
    
- 
    
     
    
    
             
      return {
     
    
- 
    
     
    
    
     
                  num,
     
    
- 
    
     
    
    
     
                  arr
     
    
- 
    
     
    
    
     
              }
     
    
- 
    
     
    
    
     
          },
     
    
- 
    
     
    
    
         
      render(
      ) {
     
    
- 
    
     
    
    
             
      return (
     
    
- 
    
     
    
    
                 
      <>
     
    
- 
    
     
    
    
                     
      <div>{this.num}
      </div>
     
    
- 
    
     
    
    
                     
      <div>hello world
      </div>
     
    
- 
    
     
    
    
     
                      {this.arr.map((item: any, index: number) => {
     
    
- 
    
     
    
    
     
                        return (
     
    
- 
    
     
    
    
                         
      <div key={index}>
     
    
- 
    
     
    
    
     
                            {item.name}:{item.value}
     
    
- 
    
     
    
    
                         
      </div>
     
    
- 
    
     
    
    
     
                        )
     
    
- 
    
     
    
    
     
                      })}
     
    
- 
    
     
    
    
                 
      </>
     
    
- 
    
     
    
    
     
              )
     
    
- 
    
     
    
    
     
          }
     
    
- 
    
     
    
    
     
      })
     
    
 return: (推荐)
  
   - 
    
     
    
    
     
      import { defineComponent, ref, reactive } 
      from 
      'vue';
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
     
      export 
      default 
      defineComponent({
     
    
- 
    
     
    
    
         
      setup(
      ){
     
    
- 
    
     
    
    
             
      interface 
      Item {
     
    
- 
    
     
    
    
     
                  [
      T: 
      string]: 
      any
     
    
- 
    
     
    
    
     
              }
     
    
- 
    
     
    
    
             
      const num = ref<
      number>(
      0)
     
    
- 
    
     
    
    
             
      const arr = reactive<
      Array<
      Item>>([])
     
    
- 
    
     
    
    
             
      return 
      () => (
     
    
- 
    
     
    
    
                 
      <>
     
    
- 
    
     
    
    
                     
      <div>{num.value}
      </div>
     
    
- 
    
     
    
    
                     
      <div>hello world
      </div>
     
    
- 
    
     
    
    
     
                      {arr.map((item: any, index: number) => {
     
    
- 
    
     
    
    
     
                        return (
     
    
- 
    
     
    
    
                         
      <div key={index}>
     
    
- 
    
     
    
    
     
                            {item.name}:{item.value}
     
    
- 
    
     
    
    
                         
      </div>
     
    
- 
    
     
    
    
     
                        )
     
    
- 
    
     
    
    
     
                      })}
     
    
- 
    
     
    
    
                 
      </>
     
    
- 
    
     
    
    
     
              )
     
    
- 
    
     
    
    
     
          }
     
    
- 
    
     
    
    
     
      })
     
    
 7.2、如何解决tsx下多节点问题?
vue3及以上 新增fragment特性,可以直接写多个根节点,vue2想要实现多个根节点,安装依赖 vue-fragment
注意:vue-fragment 是在vue2项目里用的!
  
   - 
    
     
    
    
     
      // main.ts
     
    
- 
    
     
    
    
     
      import 
      Fragment 
      from 
      'vue-fragment'
     
    
- 
    
     
    
    
     
      Vue.
      use(
      Fragment.
      Plugin)
     
    
使用方式如下,其实就是绕过vue的内核编译,然后在渲染时,会将最外层fragment节点删除掉,就不会有多出一层div的结构了,在react里也有类似的结构, React.Fragment 或者 <></>语法糖
vue2 + tsx方式:
  
   - 
    
     
    
    
     
      import { defineComponent, toRefs } 
      from 
      '@vue/composition-api';
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
     
      export 
      default 
      defineComponent({
     
    
- 
    
     
    
    
       
      name: 
      'MenuItem',
     
    
- 
    
     
    
    
       
      props: {
     
    
- 
    
     
    
    
         
      icon: {
     
    
- 
    
     
    
    
           
      type: 
      String,
     
    
- 
    
     
    
    
           
      default: 
      ''
     
    
- 
    
     
    
    
     
          }
     
    
- 
    
     
    
    
     
        },
     
    
- 
    
     
    
    
       
      setup(
      props) {
     
    
- 
    
     
    
    
         
      const { icon } = 
      toRefs(props)
     
    
- 
    
     
    
    
         
      return 
      () => (
     
    
- 
    
     
    
    
           
      <fragment>
     
    
- 
    
     
    
    
     
              {icon.value && (() => {
     
    
- 
    
     
    
    
     
                if (icon.value.includes('el-icon')) {
     
    
- 
    
     
    
    
     
                  return 
      <i class={[icon.value, 'sub-el-icon']} style={{ color: 'currentColor', width: '1em', height: '1em' }} />
     
    
- 
    
     
    
    
     
                } else if (icon.value.includes('yxp_nav')) {
     
    
- 
    
     
    
    
     
                  return 
      <i class={[icon.value, 'yxp_nav']} />
     
    
- 
    
     
    
    
     
                } else {
     
    
- 
    
     
    
    
     
                  return 
      <svg-icon icon-class={icon.value}/>
     
    
- 
    
     
    
    
     
                }
     
    
- 
    
     
    
    
     
              })()}
     
    
- 
    
     
    
    
           
      </fragment>
     
    
- 
    
     
    
    
     
          )
     
    
- 
    
     
    
    
     
        }
     
    
- 
    
     
    
    
     
      })
     
    
 vue3 + tsx: 默认支持fragment,不需要额外写进去
  
   - 
    
     
    
    
     
      import { defineComponent, ref, reactive } 
      from 
      'vue';
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
     
      export 
      default 
      defineComponent({
     
    
- 
    
     
    
    
         
      setup(
      ){
     
    
- 
    
     
    
    
             
      interface 
      Item {
     
    
- 
    
     
    
    
     
                  [
      T: 
      string]: 
      any
     
    
- 
    
     
    
    
     
              }
     
    
- 
    
     
    
    
             
      const num = ref<
      number>(
      0)
     
    
- 
    
     
    
    
             
      const arr = reactive<
      Array<
      Item>>([])
     
    
- 
    
     
    
    
             
      return 
      () => (
     
    
- 
    
     
    
    
                 
      <>
     
    
- 
    
     
    
    
                     
      <div>{num.value}
      </div>
     
    
- 
    
     
    
    
                     
      <div>hello world
      </div>
     
    
- 
    
     
    
    
     
                      {arr.map((item: any, index: number) => {
     
    
- 
    
     
    
    
     
                        return (
     
    
- 
    
     
    
    
                         
      <div key={index}>
     
    
- 
    
     
    
    
     
                            {item.name}:{item.value}
     
    
- 
    
     
    
    
                         
      </div>
     
    
- 
    
     
    
    
     
                        )
     
    
- 
    
     
    
    
     
                      })}
     
    
- 
    
     
    
    
                 
      </>
     
    
- 
    
     
    
    
     
              )
     
    
- 
    
     
    
    
     
          }
     
    
- 
    
     
    
    
     
      })
     
    
 react方式:
  
   - 
    
     
    
    
     
      class 
      Columns 
      extends 
      React.Component {
     
    
- 
    
     
    
    
       
      render(
      ) {
     
    
- 
    
     
    
    
         
      return (
     
    
- 
    
     
    
    
           
      <React.Fragment>
     
    
- 
    
     
    
    
             
      <div>Hello
      </div>
     
    
- 
    
     
    
    
           
      </React.Fragment>
     
    
- 
    
     
    
    
     
          );
     
    
- 
    
     
    
    
     
        }
     
    
- 
    
     
    
    
     
      }
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
     
      或者
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
     
      class 
      Columns 
      extends 
      React.Component {
     
    
- 
    
     
    
    
       
      render(
      ) {
     
    
- 
    
     
    
    
         
      return (
     
    
- 
    
     
    
    
           
      <>
     
    
- 
    
     
    
    
             
      <div>Hello
      </div>
     
    
- 
    
     
    
    
           
      </>
     
    
- 
    
     
    
    
     
          );
     
    
- 
    
     
    
    
     
        }
     
    
- 
    
     
    
    
     
      }
     
    
 7.3、 vue3 + tsx 下的el-form表单使用?
下面我以填写手机号和验证码的表单来举例
  
   - 
    
     
    
    
     
      import { defineComponent, ref, reactive } 
      from 
      'vue';
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
     
      export 
      default 
      defineComponent({
     
    
- 
    
     
    
    
         
      setup(
      ){
     
    
- 
    
     
    
    
             
      const formData = reactive<{
      mobile: 
      string, 
      verifyCode: 
      string}>({
     
    
- 
    
     
    
    
               
      mobile: 
      '',
     
    
- 
    
     
    
    
               
      verifyCode: 
      ''
     
    
- 
    
     
    
    
     
              })
     
    
- 
    
     
    
    
             
      const 
      checkPhone = (
      rule, value, callback) => {
     
    
- 
    
     
    
    
               
      const reg = 
      /^1[3456789]\d{9}$/
     
    
- 
    
     
    
    
               
      if (reg.
      test(value)) {
     
    
- 
    
     
    
    
                 
      return 
      callback();
     
    
- 
    
     
    
    
     
                }
     
    
- 
    
     
    
    
               
      callback(
      '请输入正确格式的手机号码!');
     
    
- 
    
     
    
    
     
              }
     
    
- 
    
     
    
    
             
      const rules = 
      reactive({
     
    
- 
    
     
    
    
               
      mobile: [
     
    
- 
    
     
    
    
     
                  { 
      required: 
      true, 
      validator: checkPhone, 
      message: 
      '请输入正确格式的手机号码', 
      trigger: 
      'blur' }
     
    
- 
    
     
    
    
     
                ],
     
    
- 
    
     
    
    
               
      verifyCode: [
     
    
- 
    
     
    
    
     
                  { 
      required: 
      true, 
      message: 
      '请输入短信验证码!', 
      trigger: 
      'blur' }
     
    
- 
    
     
    
    
     
                ]
     
    
- 
    
     
    
    
     
              })
     
    
- 
    
     
    
    
             
      const form = 
      ref(
      null)
     
    
- 
    
     
    
    
             
      return 
      () => (
     
    
- 
    
     
    
    
                 
      <el-form
     
    
- 
    
     
    
    
     
       ref={form}
     
    
- 
    
     
    
    
     
       rules={rules}
     
    
- 
    
     
    
    
     
       props={{
     
    
- 
    
     
    
    
     
       model: formData
     
    
- 
    
     
    
    
     
       }}
     
    
- 
    
     
    
    
     
       >
     
    
- 
    
     
    
    
                     
      <el-form-item prop='mobile'>
     
    
- 
    
     
    
    
                       
      <el-input
     
    
- 
    
     
    
    
                         
      v-model=
      {formData.mobile}
     
    
- 
    
     
    
    
                         
      placeholder=
      '请输入手机号'
     
    
- 
    
     
    
    
     
                        >
     
    
- 
    
     
    
    
                         
      <i slot='prefix' class={['el-input__icon']} />
     
    
- 
    
     
    
    
                       
      </el-input>
     
    
- 
    
     
    
    
                     
      </el-form-item>
     
    
- 
    
     
    
    
                     
      <el-form-item prop='verifyCode'>
     
    
- 
    
     
    
    
                       
      <el-input
     
    
- 
    
     
    
    
                         
      v-model=
      {formData.verifyCode}
     
    
- 
    
     
    
    
                         
      placeholder=
      '请输入短信验证码'
     
    
- 
    
     
    
    
     
                        >
     
    
- 
    
     
    
    
                         
      <i slot='prefix' class={['el-input__icon']} />
     
    
- 
    
     
    
    
                       
      </el-input>
     
    
- 
    
     
    
    
     
                        {
     
    
- 
    
     
    
    
     
                          verShow.value ? 
      <el-button
     
    
- 
    
     
    
    
                           
      获取短信验证码
     
    
- 
    
     
    
    
     
                          </
      el-button> : 
      <el-button>
     
    
- 
    
     
    
    
                           
      <span>{timer.value}
      </span>秒后重新获取
     
    
- 
    
     
    
    
                         
      </el-button>
     
    
- 
    
     
    
    
     
                        }
     
    
- 
    
     
    
    
                     
      </el-form-item>
     
    
- 
    
     
    
    
                     
      <el-form-item>
     
    
- 
    
     
    
    
                       
      <el-button
     
    
- 
    
     
    
    
     
                        >确定
      </el-button>
     
    
- 
    
     
    
    
                       
      <el-button
     
    
- 
    
     
    
    
     
                        >取消
      </el-button>
     
    
- 
    
     
    
    
                     
      </el-form-item>
     
    
- 
    
     
    
    
                   
      </el-form>
     
    
- 
    
     
    
    
     
              )
     
    
- 
    
     
    
    
     
          }
     
    
- 
    
     
    
    
     
      })
     
    
 那么这里其实有两个不容易解决的点:
1、Invalid handler for event "input": got undefined

解决方法如下:
  
   - 
    
     
    
    
     
                  <el-form
     
    
- 
    
     
    
    
     
                      ref={form}
     
    
- 
    
     
    
    
     
                      rules={rules}
     
    
- 
    
     
    
    
     
                      props={{
     
    
- 
    
     
    
    
                       
      model: formData
     
    
- 
    
     
    
    
     
                      }}
     
    
- 
    
     
    
    
     
                    >
     
    
- 
    
     
    
    
     
                   </el-form>
     
    
2、Cannot add property isRootInsert, object is not extensible

出现这个问题的原因是v-show不能同时出现在同一级上,应该跟v-if的方式一样,使用三目运算符,解决方法如下:
  
   - 
    
     
    
    
     
                        {
     
    
- 
    
     
    
    
     
                          verShow.
      value ? 
      <el-button>
     
    
- 
    
     
    
    
     
                            获取短信验证码
     
    
- 
    
     
    
    
                         
      </el-button> : 
      <el-button>
     
    
- 
    
     
    
    
                           
      <span>{timer.value}
      </span>秒后重新获取
     
    
- 
    
     
    
    
                         
      </el-button>
     
    
- 
    
     
    
    
     
                        }
     
    
转载:https://blog.csdn.net/qq_39404437/article/details/128562320
 
					