Vite TSX Vue3组件开发快速入门

各位掘金的小伙伴,大家好!沉寂了一段时间,小卷又和大伙儿见面了。这次我们一起来卷Vue3自研组件库实战。本套专栏小卷会采用Vue3开发的最新的技术栈,从手把手环境搭建到各个组件开发的设计思想、代码实现、重构到组件发布等一系列流程都会涵盖到,小伙伴们赶快关注起来吧!

基本工程环境

node环境

友情提醒:为了避免软件以及依赖版本不一致造成的学习阻碍问题,跟随一起学习的小伙伴请务必保证自己使用的工具和依赖版本和小卷教程中的保持一致哦~ node采用较新的稳定版本:18.18.2,这数字还挺吉利的~随之一起安装的npm版本为9.8.1。node软件的下载与安装这里就略过了,顺便提下本地缓存的npm目录的位置可以用下面的命令来自行设定:

shell 复制代码
# 设置全局模块安装目录
npm config set prefix /path/to/global/modules
# 设置npm缓存目录
npm config set cache /path/to/npm/cache

设置完成后,不要忘了将路径/path/to/global/modules配置到Path环境变量中,以便可以在命令行直接访问全局安装的npm工具命令哦~ 为方便管理npm源,咱们全局安装一个好用的工具nrm

shell 复制代码
npm i -g nrm

该工具的使用很简单:

shell 复制代码
# 查看npm源列表
nrm ls
# 切换npm源
nrm use taobao

vite工程初始化

vite工程的初始化可以交给vite命令行工具,全局安装下该工具:

shell 复制代码
npm i -g vite

然后就可以在命令行中进行vite工程的初始化了,使用交互式命令,设置工程创建选项即可:

shell 复制代码
npm init vite

这里我们先提供一个最精简的vite版的vue3工程。里面的依赖项仅包含了:

json 复制代码
{
  ...
  "dependencies": {
    "vue": "^3.4.21"
  },
  "devDependencies": {
    "@vitejs/plugin-vue": "^5.0.4",
    "vite": "^5.2.0"
  }
}

最基本的vue3版本的依赖,以及vite和它与vue相关的插件。后续的其他插件和工具的集成,咱们将在这个最简化的版本上一点点升级。 作为vue工程,需要告诉vite去配置vue插件。我们看到在项目根路径下vite.config.js就是用来对vite进行各种插件集成以满足各类型项目构建需求的。很显然,这里我们仅使用了vue插件:

js 复制代码
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [vue()],
})

Vue3工程代码结构

这里我们只关注vite构建单页面的Vue3应用,页面的入口自然是最外层的index.html,这里会通过module的形式来导入入口的main.js

html 复制代码
...
<html lang="en">
  <head>
    ...
  </head>
  <body>
    <div id="app"></div>
    <script type="module" src="/src/main.js"></script>
  </body>
</html>

在入口的src/main.js中将完成根组件App的创建与挂载,并导入全局的样式文件:

js 复制代码
import { createApp } from 'vue'
import './style.css'
import App from './App.vue'

createApp(App).mount('#app')

我们先不对页面样式做过多的修饰,简单设置一个柔和的背景色: src/style.css

css 复制代码
body {
  background: #fcfdf5;
}

再来看根组件App,这里我们采用Vue3提供的setup新语法来完成"只声明,免注册"的舒适编程风格,来注册并使用HelloWorld组件: src/App.vue

html 复制代码
<script setup>
import HelloWorld from './components/HelloWorld.vue'
</script>

<template>
  <div>
    <h3>一个最简单的Vue3应用</h3>
  </div>
  <HelloWorld msg="hello Vue3" />
</template>

<style scoped>
</style>

注意,在Vue3中组件模板不再要求只能有一个根元素了哦~

最后是组件HelloWorld,一起来看下,这里咱们通过隐式属性定义函数defineProps声明了一个可以从外部传入消息的msg属性。通过ref函数对一个计数器变量count提升为响应式变量,以实现页面点击按钮时能看到计数器值的实时变化: src/components/HelloWorld.vue

html 复制代码
<script setup>
import { ref } from 'vue'

defineProps({
  msg: String,
})

const count = ref(0)
</script>

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

  <div>
    <button type="button" @click="count++">count is {{ count }}</button>
  </div>
</template>

<style scoped>
</style>

安装和启动应用

在项目根路径下执行:

shell 复制代码
npm i

启动服务

shell 复制代码
npm run dev

页面效果:

集成jsx

jsx的语法可以很容易的实现在js脚本中进行组件html内容的动态渲染,这种形式比起传统的html标签中应用vue指令的形式,具有更好的语义和可读性;同时也让html模板的渲染变得更灵活。

安装插件

shell 复制代码
npm i -D @vitejs/plugin-vue-jsx@3.1.0

温馨提醒:这里为了和教程中用的版本保持一致,特意把安装的版本进行了指定哦~

配置插件

vite.config.js

js 复制代码
...
import vueJsx from '@vitejs/plugin-vue-jsx'
​
export default defineConfig({
  plugins: [..., vueJsx()],
})
​

现在,咱们对之前开发的AppHelloWorld两个组件用jsx语法进行改写吧。 关于vue3中具体的jsx语法,大伙儿可以参考下官方技术文档《渲染函数 & JSX》,这里咱们只用它来完成vue单文件组件的改写。

温馨提示

小卷在采用智能编辑器webstorm编辑.jsx后缀的文件时,代码的缩进并不是自己期望的,折腾了下,发现在工程根目录下加一个.editorconfig文件就解决问题啦~

ini 复制代码
root = true

[*]
indent_style = tab
indent_size = 2

src/App.jsx

jsx 复制代码
import { defineComponent } from 'vue'
import HelloWorld from './components/HelloWorld'

export default defineComponent({
  setup() {
    return () => {
      return (
     <div>
      <div>
       <h3>一个最简单的Vue3应用</h3>
      </div>
      <HelloWorld msg="hello Vue3"/>
     </div>
    )
   }
  }
})

这里我们通过接收一个vue组件的配置对象并调用defineComponent函数,来导出一个vue组件。要返回的模板内容写在setup钩子的回调中,这里的内容很简单,都是静态的,但要注意jsx返回的html内容必须只能有一个根元素哦App组件在main.js中导入时,可以省略后缀的.jsx

js 复制代码
import App from './App'

src/components/HelloWorld.jsx

该组件模板中会渲染动态的内容,并多了按钮的交互。这里绑定表达式、变量的输出值以及绑定事件处理函数的调用逻辑都是写在{ ... }中,注意要和传统vue单文件中模板用{{ ... }}小胡子语法区别开哦。特别要注意的是,响应式变量在jsx中输出时不能省略.value的引用哦~

jsx 复制代码
import { defineComponent, ref } from 'vue'

export default defineComponent({
  props: {
   msg: String
  },
  setup(props) {
   const { msg } = props
   const count = ref(0)
   return () => {
    return (
     <div>
      <h1>{ msg }</h1>
      <div>
       <button type='button' onClick={ () => count.value++ }>count is { count.value }</button>
      </div>
     </div>
    )
   }
  }
})

另外,注意下组件属性的定义和使用方式。

集成Typescript

为了进一步让前端的代码有更高的可读性和可维护性,是时候引入typescript了。依赖安装:

shell 复制代码
npm i -D typescript@5.4.5 vue-tsc@2.0.14

这里除了安装基本的ts库,还要安装vue组件对于ts语法的编译器工具vue-tsc。 还需要在工程根目录下准备两个ts的配置文件:tsconfig.jsontsconfig.node.json,这两个文件可以在使用vite命令行工具生成项目指定使用typescript时,自动生成,这里就不贴出配置内容了,也可以在小卷的github代码库中获得参考。

接下来我们的重心是对工程中所有.js.jsx后缀的文件进行相应的改写,改写为.ts.tsx文件,只要修改文件名,内容不变动。涉及修改的文件包括:

  • vite.config.ts
  • src/main.ts
  • src/App.tsx
  • src/components/HelloWorld.tsx 不要忘了在index.html中引入main.ts也要调整下哦。 为了在启动dev服务时能对ts进行编译,咱们对package.json中的dev命令脚本进行调整:
json 复制代码
{
  ...
  "scripts": {
    "dev": "vue-tsc && vite",
    ...
  }
  ...
}

执行npm run dev,报如下的错误:

解决办法: 在tsconfig.jsoncompilerOptions配置选项下加一个配置项"jsxImportSource": "vue",告诉tsc编译器在编译jsx的模板中的内容时以vue作为导入源。

现在我们用ts来封装HelloWorld组件的属性类型,以提供更好的类型检查。为此,我们对HelloWorld组件string类型的msg属性做一下调整,封装一个IMsg类型。新建ts文件: src/components/types.ts

ts 复制代码
import { ExtractPropTypes, PropType } from 'vue'
// 导出vue的属性定义
export const props = {
  msg: {
   // 类型为自定义的属性类型,这里对Object的属性类型采用了泛型的形式以精确到具体的ts类型
   type: Object as PropType<IMsg>,
   required: true
  }
} as const // 将其作为一个常量导出,对外部是只读的
// 对Vue的属性定义对象进行ts类型的提取,以方便外部对属性的ts类型进行识别
export type Props = ExtractPropTypes<typeof props>

// 自定义消息类型
export interface IMsg {
  info: string
}

src/components/HelloWorld.tsx

tsx 复制代码
...
import { props, Props } from './types'

export default defineComponent({
  props, // 使用导入的属性定义
  // 对实际的属性配置声明包装类型
  setup(props: Props) {
   ...
   return () => {
    return (
     <div>
      <h1>{ msg.info }</h1>
      ...
     </div>
    )
   }
  }
})

这里咱们引入定义的属性配置及其类型。 App组件在使用HelloWorld组件进行属性定义的地方相应的做一下调整:

src/App.tsx

tsx 复制代码
...

export default defineComponent({
  setup() {
   return () => {
    return (
     <div>
      ...
      <HelloWorld msg={ { info: 'hello tsx!!!' } }/>
     </div>
    )
   }
  }
})

显然这里我们要传入满足类型的参数,否则对于集成了ts检查的编辑器以及运行vue-tsc命令时都会得到类型检查错误信息:

ok!小伙伴们,学到这里咱们对采用tsx来开发Vue3组件进行了一个快速的尝鲜,想必大家尝到一点前端组件规范化开发的甜头,这还不够,下一小节,咱们还将进一步集成eslintprettier以及结合编辑器插件的自动修复不规范的代码来进一步优化我们的前端开发环境,等这些都做到位了,我们将一起来写一个高性能的Tree组件来打开咱们组件化实践的序幕,大家加油!

相关推荐
|晴 天|17 分钟前
从零打造现代化个人博客:Vue 3 + TypeScript + Element Plus 完整实战
javascript·css·chrome·typescript·html5·webstorm
大萝卜呼呼1 小时前
Next.js第十七课 - 部署
前端·typescript·next.js
只会写Bug1 小时前
后台管理项目中关于新增、编辑弹框使用的另一种展示形式
前端·vue.js
M ? A2 小时前
Vue v-bind 转 React:VuReact 怎么处理?
前端·javascript·vue.js·经验分享·react.js·面试·vureact
军军君012 小时前
数字孪生监控大屏实战模板:政务服务大数据
前端·javascript·vue.js·typescript·前端框架·echarts·less
忆往wu前3 小时前
前端请求三部曲:Ajax / Fetch / Axios 演进与 Vue 工程化封装
前端·vue.js
.Cnn3 小时前
Ajax与Vue 生命周期核心笔记
前端·javascript·vue.js·笔记·ajax
吴声子夜歌4 小时前
Vue3——渲染函数
前端·vue.js·vue·es6
Ruihong4 小时前
你的 Vue KeepAlive 组件,VuReact 会编译成什么样的 React 代码?
vue.js·react.js·面试
Ruihong4 小时前
你的 Vue slot 插槽,VuReact 会编译成什么样的 React 代码?
vue.js·react.js·面试