基础知识
- 组件命令规则
官方建议我们使用大驼峰命名法注册组件
- 单词大写开头对于编辑器的自动补全比较友好
- 能够与基础的HTML元素区分
- 基础组件(也就是展示类的、无逻辑的或无状态的组件)应该以Base,App开头;eg: BaseButton, BaseTable
- 属性定义Prop
使用更细节的方式定义属性
<script setup> // 不推荐 const props = defineProps(['title']) // 推荐 const props = defineProps({ title: { type: String, required: true, default: '' } }) </script> - 事件定义emit
自定义事件的名称会被自动做转换,我们通常使用驼峰做事件名,但监听时需要转换为横线连接方式(kebab-base)
<!-- MyComponent --> <script setup> const emit = defineEmits('someEvent') emit('someEvent') </script> <!-- 使用页面 --> <MyComponent @some-event="callback" /> - 透传特性
那些没有在props和emits中声明的特性或者事件监听被称为透传特性, 比如class, style, id这些,当组件只有一个根节点时, 透传特性会默认加到根元素上;多个根节点则不存在// 如果不需要继承这些属性 需要使用inheritAttrs: false <script> // use normal <script> set this option export default { inheritAttrs: false } </script> <script setup> // 访问透传特性 import { useAttrs } from 'vue' const attrs = useAttrs() </script>
TSX in Vue3
在TSX文件中定义组件
- 函数式组件
export default (props, ctx) => <div>test<div>
- defineComponent + render函数式
// render函数内部需要使用this
export default defineComponent({
render() {
return <div>test</div>
}
})
- defineComponent + setup
export default defineComponent({
setup(props, ctx) {
// 利用Composition API,避免this
return <div>test</div>
}
})
vue3中的JSX语法
- JSX中使用修饰符
// button.tsx
import { withModifiers, defineComponet, ref } from 'vue'
export default defineComponet({
const count = ref(0)
const inc = () => count.value++
setup(props) {
return () => {
return
<>
<a href="" onClick={withModifiers(inc, ['prevent'])}>click</a>
<button onClick={withModifiers(inc, ['self'])}> click Me </button>
</>
}
}
})
- JSX中使用指令v-if/v-for
v-if使用条件语句或三元表达式代替
v-for通过map循环来替换
// test.jsx
import { defineComponet, ref } from 'vue'
export default defineComponet({
const condition = ref(true)
const list = ref([1,2,3,4])
setup() {
return () => {
<div>{ condition ? <span>A</span> : <span></span> }</div>
<ul>
list.map(item => {
return <li> {item} </li>
})
</ul>
}
}
})
- JSX中使用插槽
通过v-slots指令 指定具名插槽
// Parent.txs
import { defineComponent } from 'vue'
export default defineComponet({
setup() {
return () => {
return (
<Child v-slots={{
prefix: () => <i>prefix</i>,
suffix: (props: Record<"name", String>) => <i>{props.name}</i>
}}>
<!--默认插槽-->
</Child>
)
}
}
})
// Child.tsx
import { defineComponent } from 'vue'
export default defineComponet({
setup(props, { slots }) {
return () => (
<>
默认插槽:{ slots.default && slots.default() }
<br />
具名插槽:{ slots.prefix && slots.prefix() }
<br />
作用域插槽:{ slots.suffix && slots.suffix({name: 'suffix'})}
</>
)
}
})
- JSX中使用emit
import { defineComponent } from 'vue'
export default defineComponent({
emits: ['click'],
setup(props, {emit}) {
return () => (
<button onClick={() => emit('click', 'msg')}>子向父传递</button>
)
}
})
基础环境搭建
项目创建(基于vite创建)
创建基础模板
- 使用npm
npm init vite@latest
// 依次输入project-name
// 选择vue
// 选择vue-ts版本
- 使用yarn
yarn create vite
- 使用pnpm
pnpm create vite
引入JSX
通过@vitejs/plugin-vue-jsx插件
yarn add @vitejs/plugin-vue-jsx -D
在vite.config.ts中配置jsx插件
import vueJSX from '@vitejs/plugin-vue-jsx'
export default {
plugins: [
//...
vueJSX({
// 配置项
})
]
}
代码规范(eslint + prettier)
eslint配置
使用eslint --init 初始化配置文件
npx eslint --init
依次执行如下操作:
适配vue3语法
//.eslintrc.js
module.exports = {
extends: [
"plugin:vue/vue3-recommended"
]
}
添加prettier
- 安装插件
yarn add -D prettier eslint-plugin-prettier eslint-config-prettier
- 修改.eslintrc.js
module.exports = {
extends: [
plugin:vue/vue3-recommended",
"plugin:prettier/recommended"
]
}
- 创建.prettierrc.js
module.exports = {
// printWidth: 80,
// tabWidth: 2,
// useTabs: false,
semi: false, // 未尾逗号, default: true
singleQuote: true, // 单引号 default: false
// quoteProps: 'as-needed',
// jsxSingleQuote: false,
trailingComma: 'none', // 未尾分号 default: es5 all | none | es5
// bracketSpacing: true,
// bracketSameLine: false,
// jsxBracketSameLine: false,
arrowParens: 'avoid', // default: always
// insertPragma: false,
// requirePragma: false,
proseWrap: 'never',
// htmlWhitespaceSensitivity: 'css',
// vueIndentScriptAndStyle: false, // .vue 缩进
endOfLine: 'auto' // default lf
}
文档系统(vitepress)
添加vitePress文档
- 安装vitepress
yarn add -D vitepress
- 创建第一个文档
mkdir docs && echo "hello vitepress" > docs/index.md
- 添加脚本
// package.json
{
"scripts": {
"docs:dev": "vitepress dev docs",
"docs:build": "vitepress build docs",
"docs:serve": "vitepress serve docs"
}
}
- 本地启动
yarn docs:dev
配置vitepress
- 配置左侧菜单
// 修改 docs/.vitepress/config.ts文件 没有则创建该文件
const sidebar = [
{
text: '组件',
items: [
{ text: 'Button 按钮', link: '/components/button/' },
{ text: 'Tree 树形控件', link: '/components/tree/' },
{ text: 'Input 输入框', link: '/components/input/' },
{ text: 'Select 选择器', link: '/components/select/' },
{ text: 'Table 表格', link: '/components/table/' },
]
}
]
export default {
themeConfig: {
sidebar
}
}
- 创建左侧菜单对应的md文件
// 在docs/components依次创建button、tree、input等文件夹以及对应的index.md文件
样式体系(sass + tailwind.css)
- 安装sass + tailwind
npm install -D sass tailwindcss postcss autoprefixer
- 初始化tailwind
npx tailwindcss init -p
- 配置tailwind
// tailwind.config.js
module.exports = {
content: [
"./index.html",
"./src/**/*.{vue,js,ts,jsx,tsx}",
],
theme: {
extend: {},
},
plugins: [],
}
- 添加Tailwind指令到主样式文件
/* index.scss */
@import "tailwindcss/base";
@import "tailwindcss/components";
@import "tailwindcss/utilities";