暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

【组件库从0到1】Vite + Vue3 + TSX开发指南

村长学前端 2021-12-15
2273

前言

不少前端小伙伴问过我,说业务代码写了2、3年了,应该如何再进一步?村长的回答中大多数会提到两个关键点:加强工程化实践能力底层原理源码知识工程化能力对于小伙伴们在工作中解决问题有直接影响,如果你想成为小组内的核心程序员,拿更高的职位和薪资,能够给大家搭架子,解决问题,重难点突破是非常关键的几个考察点。实践中,我们如何刻意提升自己这方面的能力,我觉得给公司搭建一套组件库就很好。在这个过程中大家需要解决不少工程问题,比如:
  • 如何构建一个敏捷的开发、发布环境
  • 如何实现组件库文档系统
  • 引入jsx/tsx
  • 组件的设计与编写
  • 代码质量:eslint、单测等
  • 风格化、国际化等

这些任务对于日常和业务打交道的同学来说当然很有挑战性,12月16日,村长特意准备了一节0元公开课《vue3+ts组件库开发实战》,本次课准备给小伙伴们实战一下Tree组件的开发,深度体验vue3+tsx开发的各种知识点。

报名链接

知识储备

本次我要带大家编写一个Tree组件,会用到JSX,因此我们提前做一些知识储备:

  • 配置Vite支持JSX

  • Vue3中的JSX:jsx-next语法学习

Vite中引入JSX

本次Tree组件实现要用到JSX支持,所以小伙伴们有必要先了解如何在Vite项目中引入JSX。

我们可以通过一个叫做@vitejs/plugin-vue-jsx插件实现,

首先安装它:

yarn add @vitejs/plugin-vue-jsx -D

配置一下该插件,vite.config.ts

// vite.config.js
import vueJsx from '@vitejs/plugin-vue-jsx'

export default {
  plugins: [
    vueJsx({
      // options are passed on to @vue/babel-plugin-jsx
    })
  ]
}

测试一下,components/Tree.tsx

export default () => <div>tree</div>

如何定义一个组件

在TSX文件中定义组件有几种常用方式:

  • 函数式组件:最简单的方式,你可以把它理解为setup
    函数,但是不同之处它可以直接返回JSX
export default (props, ctx) => <div>tree</div>

  • defineComponent
    :传递render
    选项,也就是Options API,这种缺点是要访问this
export default defineComponent({
render() {
return <div>tree</div>
}
})

  • defineComponent:传递setup
    选项,利用Composition API,避免this
    ,是推荐的形式
export default defineComponent({
setup(props, ctx) {
return () => <div>tree</div>
}
})

Vue3中JSX/TSX特殊语法

如果有过react的开发经验,可以发现除了vue中独有的几个新概念:slot
directive
emit
等以外,其他都是相同的,因此这里仅关注这些特殊部分:

指令

指令使用需要我们转换思维,有几种不同情况:

  • 常用指令v-model,v-show跟以前用法类似,但也要注意后面是{}
    ,不是""
<input type="text" v-model={this.counter} />

  • v-if使用条件语句或三元表达式代替
<div>{ condition ?  <span>A</span> : <span>B</span> }</div>

  • v-for使用map代替
import { defineComponent, ref } from "vue";
const App = defineComponent({
setup(){
const list = ref<string[]>([])
return () => {
list.value.map((data,index) => <p key={index}>{data}</p>)
}
}
});


插槽

JSX中想要实现Vue中的插槽写法也有很大不同,主要利用一个叫做v-slots
的指令来实现:

Parent.tsx

export default defineComponent({
setup() {
return () => (
<Child
v-slots={{
prefix: () => <i>prefix</i>, // 具名插槽
suffix: (props: Record<"name", string>) => <span>{props.name}</span>, // props可作插槽作用域的作用
}}
>
默认插槽内容
</Child>
);
},
});

const Child = defineComponent({
setup(props, { slots }) {
return () => (
<>
默认插槽: {slots.default && slots.default()}
<br />
具名插槽: {slots.prefix && slots.prefix()}
<br />
作用域插槽:{slots.suffix && slots.suffix({ name: "suffix" })}
</>
);
},
});

emit

vue中子向父传值一般都是emit的方式,这个在vue3中大致写法相似,只是多了一个定义emit的步骤,这也是为了后续的类型推倒做准备。

defineComponent({
emits: ["click"],
setup(props ,{ emit }) {
return () => (
<button onClick={() => {emit("click")}}>点我触发emit</button>
);
},
});


村长公开课

12月16日的公开课将会展开Vue3+TSX这个话题,以一个Tree组件的实现作为驱动,干货多多,欢迎大家参加!


文章转载自村长学前端,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论