小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。
Vue3 + TS 开发前端组件库 丨走进 JSX
如何用 ts 在 vue3 中定义组件?
如何提取 props 定义?
vue 中 h 函数是什么?
setup 的运用和其意义
setup 如何返回 render 函数?
如何使用 jsx 开发 vue3 组件?
一步步走向 JSX
如何用 ts 在 vue3 中定义组件?
Component 接口
defineComponent 函数 定义组件 (ts 中必须使用, 它返回组件的定义)
import { defineComponent, PropType } from 'vue'
interface Config {
name: string
}
export default defineComponent({
name: 'App',
props: {
age: {
type: Number as PropType<number>
},
config: {
type: Object as PropType<Config>,
required: true
}
},
components: {},
...
})
如何提取 props 定义?
import { defineComponent } from 'vue'
const PropsType = {
msg: String,
age: {
type: Number,
required: true,
},
} as const // 声明 props 是只读Readonly的对象
export default defineComponent({
name: 'HelloWorld',
props: PropsType,
mounted() {
this.age
},
})
vue 中 h 函数是什么?
SFC 是怎么运作的?
h 函数是 createVNode 的简单的封装
import { createApp, defineComponent, h } from 'vue'
import HelloWorld from './components/HelloWorld.vue'
const img = require('./assets/logo.png') //eslint-disable-line
const App = defineComponent({
render() {
// h 相当于 createElement
// h (节点名称, 节点属性, 子类)
return h('div', { id: 'app' }, [
h('img', {
alt: 'Vue logo',
src: img,
}),
h(HelloWorld, {
msg: 'Welcome to your Vue.js + TypeScript App',
age: 12,
}),
])
},
})
createApp(App).mount('#app')
setup 的运用
export default defineComponent({
name: 'App',
setup(props, { slots, attrs, emit }) {
const state = reactive({
name: 'dmw',
})
setInterval(() => {
state.name += 1
}, 1000)
// 初始化监听并且改变的时候也会监听
watchEffect(() => {
console.log(state.name)
})
watch([xxxx, xxxx, (n, o) => {
console.log(n);
console.log(o);
document.title = n[0];
},{
deep: true,
immediate:true
});
}
return {
...toRefs(state),
}
},
})
// watch 与 watchEffect 的区别
// watch监听,可以以数组的形式监听,没有初始化监听,可加属性immediate deep ,
// 初始化监听并且改变的时候也会监听
setup 如何返回 render 函数?
import { createApp, defineComponent, h, reactive, ref } from 'vue'
// import App from './App.vue'
import HelloWorld from './components/HelloWorld.vue'
const img = require('./assets/logo.png') //eslint-disable-line
const App = defineComponent({
setup() {
const state = reactive({
name: 'dmw',
})
const numberRef = ref(1)
setInterval(() => {
state.name += 1
numberRef.value += 1
}, 2000)
return () => {
return h('div', { id: 'app' }, [
h('img', {
alt: 'Vue logo',
src: img,
}),
h('p', numberRef.value),
h(HelloWorld, {
msg: state.name,
age: 12,
}),
])
}
},
})
createApp(App).mount('#app')
如何使用 jsx 开发 vue3 组件?
Vite 安装配置 vue3-jsx支持依赖
安装 vue-jsx 支持
yarn add @vitejs/plugin-vue-jsx -D
配置 vue-jsx 插件
// vim vite.config.js
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
// 引入 jsx 依赖
import vueJsx from '@vitejs/plugin-vue-jsx'
// https://vitejs.dev/config/
export default defineConfig({
plugins: [
vue(),
vueJsx(),// 使用 vue-jsx
]
})
Webpack 安装配置 vue3-jsx 依赖
npm install @vue/babel-plugin-jsx -D
// babel.config.js
{
"plugins": ["@vue/babel-plugin-jsx"]
}
JSX 起步
修改 main.ts
import { createApp } from 'vue'
import App from './App'
createApp(App).mount('#app')
在 src 目录下新建 App.tsx
import { createApp, defineComponent, h, reactive, ref } from 'vue'
const img = require('./assets/logo.png') //eslint-disable-line
import HelloWorld from './components/HelloWorld.vue'
function renderHelloWorld(age: number) {
return <HelloWorld age={age}></HelloWorld>
}
export default defineComponent({
setup() {
const state = reactive({
name: 'dmw',
})
const numberRef = ref(1)
// setInterval(() => {
// state.name += 1
// numberRef.value += 1
// }, 2000)
return () => {
return (
<div id="app">
<img src={img} alt="" />
<p>{state.name + numberRef.value}</p>
{renderHelloWorld(18)}
</div>
)
}
},
})