VUE2进阶至VUE3七(TSX & 深入v-model)

3,888 阅读3分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第7天,点击查看活动详情

TSX

  • 介绍:

vue除了使用我们的模板语法,还可以使用TSX语法。因为有过vue2中JSX的经验,相信应该很容易上手TSX的。其实都是相通的,有不同的地方下方会详细介绍~

  • 安装:yarn add @vitejs/plugin-vue-jsx -D

  • 文件处理 vite.config.ts

import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import vueJsx from '@vitejs/plugin-vue-jsx' // 引入jsx
import { resolve } from 'path'

export default defineConfig({
  plugins: [vue(), vueJsx()], // 使用
  resolve: {
    alias: {
      '@': resolve('./src')
    }
  },
  base: './', // 打包路径
  server: {
    port: 3000, // 服务端口号
    open: true, // 服务启动时是否自动打开浏览器
    cors: true // 允许跨域
  }
})

在tsconfig.json 中添加一下代码

    "jsx": "preserve",
    "jsxFactory": "h",
    "jsxFragmentFactory": "Fragment",

最后,新建一个例如app.tsx的文件就可以开始使用tsx语法了

TSX语法介绍

  • v-modal

1、jsx中响应数据都是用单个{};

2、使用ref,reactive不会自动解包都需要用value获取值;

import { ref } from 'vue'
let input = ref<string | number>('')
const renderDom = () => {
  return (
    <div>
      <div>{input.value}</div>
      <input type="text" v-model={input.value} />
    </div>
  )
}
export default renderDom;
  • v-show 只需要正常定义变量即可
import { ref } from 'vue'
let flag = false;
const renderDom = () => {
  return (
    <div>
      <div v-show={flag}>jiang</div>
      <div v-show={!flag}>ciao</div>
    </div>
  )
}
export default renderDom;
  • v-if

不支持上述写法,不过是可以利用编程思想去编写的

import { ref } from 'vue'
let flag = false;
const renderDom = () => {
  return (
    <div>
      {flag ? <div>jiang</div> : <div>xiao</div> }
    </div>
  )
}
export default renderDom;
  • v-for 当然也是不支持的,哈哈哈, 不过 可以采用数组循环呀~ 可能看到这 有人会想了,那我干嘛不去写react,哈哈哈~ 不过,了解一下又不吃亏 嘻嘻~
import { ref } from 'vue'
let arr = ['j','x','x','j']
const renderDom = () => {
  return (
    <div>
      {arr.map(item => {
        return(<div>hah{item}</div>)
      })}
    </div>
  )
}
export default renderDom
  • 事件绑定,也是不支持的,所以直接来上代码。以点击事件以及传值为例,与vue的模板语法都略有不同。
import { ref } from 'vue'
let arr = ['j','x','x','j']
const renderDom = () => {
  return (
    <div>
      {arr.map(item => {
        return(<div onClick={handleClick.bind(this, item)}>hah{item}</div>) // 通过bind进行传值
      })}
    </div>
  )
}
const handleClick = (item:string) => {
  console.log('点击了' + item);
}
export default renderDom;

当然这里也是不支持修饰符的,所以需要我们去使用原生方法去解决。

  • props,ctx(ctx.emit)
// tsx文件
let arr = ['j','x','x','j'];
type Props = {
  title: string
}
const renderDom = (props: Props, ctx:any) => {
  return (
    <div>
      <div>{props.title}</div>
      {arr.map(item => {
        return(<div onClick={handleClick.bind(this, ctx)}>hah{item}</div>)
      })}
    </div>
  )
}
const handleClick = (ctx:any) => {
  ctx.emit('handle-click', 'jiang')
}
export default renderDom;
// 父组件
<template>
  <div class="home">
    <render-dom @handle-click="clicked" title="jiang"></render-dom>
  </div>
</template>
<script setup lang="ts">
  import renderDom from '../app';
  const clicked = (info:any) => {
    console.log('收到',info)
  }
</script>

v-model的其他用法

  • 介绍

    v-modal其实也可以应用在组件当中,它其实是通过事件的接收和派发组合在一起的。

  • 改变

    1、.sync修饰符和组件的model选项已经去掉;

    2、可以支持多个v-model进行双向数据绑定;

    3、可以支持自定义修饰符;

  • 注意: v-model在vue3中是破坏型更新;

多个v-model进行双向数据绑定

  • 代码示例:

    完成简易dialog弹窗组件。废话不多说,直接上代码~

    子组件

<template>
  <div class="dialog" v-if="isModal">
    <div class="header">
      <div>标题{{title}}</div>
      <div @click="close">x</div>
    </div>
    <div class="cotent">内容</div>
  </div>
</template>
<script setup lang="ts">
  type Props = {
    isModal: boolean,
    title: string,
  }
  defineProps<Props>(); // 接收父组件传过来的值
  const emit = defineEmits(['update:isModal', 'update:title']); //子组件将父组件所需要的值进行派发
  const close = () => {
    emit('update:isModal', false)
    emit('update:title', 'xiao')
  }
</script>

父组件

此时的父组件可以进行多个双向数据绑定~

<template>
  <div class="home">
    <button @click="flag = !flag">{{flag ? '开' : '关'}}</button>
    <div>标题:{{title}}</div>
    <Dialog v-model:isModal="flag" v-model:title="title"></Dialog>
  </div>
</template
<script setup lang="ts">
 import Dialog from '../components/dialog.vue';
 import { ref } from 'vue'
 let flag = ref<boolean>(true);
 let title = ref<string>('jiangxx')
</script>

自定义修饰符

在vue2时候官方给我们很多修饰符,例如v-model.number、v-model.trim等。在vue3中我们可以通过一个包含空对象的modelModifiers关键字进行构建自定义修饰符~

注意:当多绑定多个v-model时给其中一个添加自定义修饰符时,例如v-model:title = "title" 此时包含空对象的自定义关键字名为titleModifiers,也就是说Modifiers前面的名称要和v-model:后面的保持一致。至于,用法都是一样的

此处基于上述代码进行添加

// 父组件中添加相应的自定义修饰符v-model.jiang
<Dialog v-model:isModal="flag" v-model:title="title" v-model.jiang="flag"></Dialog>

// 子组件
<script setup lang="ts">
  type Props = {
    isModal: boolean,
    title: string,
    modelModifiers?: { // 通过此关键字添加修饰符
      jiang: boolean
    }
  }
  const data = defineProps<Props>();
  const emit = defineEmits(['update:isModal', 'update:title'])
  const close = () => {
     // 可以通过关键字进行逻辑操作
    if (data.modelModifiers?.jiang) {
      emit('update:title', 'xiao')
    } else {
      emit('update:title', 'xue')
    }
    emit('update:isModal', false)
  }
</script>

vue3虽然,有些东西没有了,但是用起来更加灵活也更加得心应手。JSX也更加的方便我们封装高级组件,感兴趣的小伙伴就抓紧入坑吧~ 用它~