Vue3使用tsx
Vue3 使用 tsx
Vue3使用tsx
Vue3 使用 tsx
安装插件
:::info npm install @vitejs/plugin-vue-jsx -D
:::
vite.config.ts 配置
1
2
3
4
5
6
7
8
9
10
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import vueJsx from '@vitejs/plugin-vue-jsx';
export default defineConfig({
plugins: [
vue(),
vueJsx()
]
})
使用TSX
tsx 不会自动解包使用
ref加.vlaue! ! !
v-model => 支持
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import { ref } from 'vue'
let v = ref<string>('')
const renderDom = () => {
return (
<>
<input v-model={v.value} type="text" />
<div>
{v.value}
</div>
</>
)
}
export default renderDom
v-show => 支持
1
2
3
4
5
6
7
8
9
10
11
12
13
14
import { ref } from 'vue'
let flag = ref(false)
const renderDom = () => {
return (
<>
<div v-show={flag.value}>景天</div>
<div v-show={!flag.value}>雪见</div>
</>
)
}
export default renderDom
v-if => 不支持
需要换一种形式
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import { ref } from 'vue'
let flag = ref(false)
const renderDom = () => {
return (
<>
{
flag.value ? <div>景天</div> : <div>雪见</div>
}
</>
)
}
export default renderDom
v-for => 不支持
需要使用Map
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import { ref } from 'vue'
let arr = [1,2,3,4,5]
const renderDom = () => {
return (
<>
{
arr.map(v=>{
return <div>${v}</div>
})
}
</>
)
}
export default renderDom
v-bind使用
直接赋值就可以
1
2
3
4
5
6
7
8
9
10
11
12
13
import { ref } from 'vue'
let arr = [1, 2, 3, 4, 5]
const renderDom = () => {
return (
<>
<div data-arr={arr}>1</div>
</>
)
}
export default renderDom
v-on
所有的事件都按照react风格来
- 所有事件有on开头
- 所有事件名称首字母大写
1
2
3
4
5
6
7
8
9
10
11
12
13
14
const renderDom = () => {
return (
<>
<button onClick={clickTap}>点击</button>
</>
)
}
const clickTap = () => {
console.log('click');
}
export default renderDom
插槽的使用
**父组件: **👇
1
2
3
4
5
6
<Page2 v-slots={{
aaa: () => <span>123</span> ,
bbb: () => <span>456</span>
}} />
**子组件: **👇
1
2
3
4
5
6
7
setup(props, { slots }) {
return () =>
<div>
我是插槽aaa: {slots.aaa && slots.aaa()} <br>
我是插槽bbb: {slots.bbb && slots.bbb()}
</div>
- 通过
v-slots返回对象,对象的每个属性为一个函数 ,返回对应的文本标签 - 根据函数的名称,调用对应的方法,来放置具名插槽的位置
- 先做个插槽的判空操作,会更加严谨
两种写法
写法一
不需要 props 来传参 , 简写
1
2
3
4
5
6
7
import { defineComponent } from 'vue';
const renderDom = defineComponent((props, {emits}) => {
return () => <div> 写法1 </div>
})
export default renderDom
defineComponent去传入一个 函数 ( 会默认为setup)- 写法方便, 因为 无法去定义
props, 所以props一直为空对象 - 但是可以正常使用
emits和slots等
写法二
需要 props 传参
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import { defineComponent } from 'vue';
const renderDom = defineComponent({
props:{
params:{
type: String,
defualt: ()=> ''
}
},
setup(props) {
return () => <div> 写法2 , 父组件传过来的值 { props.params } </div>
}
})
export default renderDom
defineComponent去传入一个 整个对象- 可以定义
props,可以使用 (父组件 => 子组件) 值 - 复杂的场景,更加推荐,使用起来更加灵活
父子组件通信
**父组件: (Father.jsx) **👇
1
2
3
4
5
6
7
8
9
10
11
12
13
14
import { defineComponent, ref } from 'vue';
import Child from './Child.jsx'
export default defineComponent(() => {
const params = ref('123')
function getChild(val){
console.log(val)
}
return () => <div>
<h3>子组件↓ </h3>
<Child params={params.value} onFather={getChild} />
</div>;
})
**子组件 : (Child.jsx) **👇
1
2
3
4
5
6
7
8
9
10
11
12
13
import { defineComponent, ref } from 'vue';
export default defineComponent({
props: ['params'],
setup(props , { emit }) {
const text = ref('传给父组件的值')
return () =>
<div>
父组件传来的值: { props.params }
<button onClick = {()=>{ emit('father', text.value) } }> 传给 father </button>
</div>
}
})
- 第二种可以定义
props的写法,才可以接收 父组件传递的参数 **emit**给父组件通信,父组件自定义 方法 要 加 on + 大写开头方法
实战代码 - 注册页
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
import { ref, reactive, defineComponent } from 'vue'
import { useRouter } from 'vue-router'
import { ElButton, ElForm, ElFormItem, ElInput } from 'element-plus'
import type { FormInstance, FormRules } from 'element-plus'
import styles from './index.module.css'
interface RuleForm {
phone: string
code: string
password: string
}
const Register = defineComponent(() => {
const router = useRouter()
const ruleForm = ref<FormInstance>()
const loginForm = reactive<RuleForm>({
phone: '',
code: '',
password: ''
})
const rules = reactive<FormRules<RuleForm>>({
phone: [
{ required: true, message: '请输入手机号', trigger: 'blur' }
],
code: [
{ required: true, message: '请输入验证码', trigger: 'blur' }
],
password: [
{ required: true, message: '请输入密码', trigger: 'blur' }
]
})
const register = async (formEl: FormInstance | undefined) => {
if (!formEl) return
await formEl.validate((valid, fields) => {
if (valid) {
console.log('submit!', loginForm)
} else {
console.log('error submit!', fields)
}
})
}
const goLogin = () => {
router.push('/login')
}
return () => <>
<div class={styles.wrap}>
<ElForm model={loginForm} rules={rules} ref={ruleForm} label-width='100px' class={styles.loginForm}>
<ElFormItem>
<h1 class={styles.title}>注册账号</h1>
</ElFormItem>
<ElFormItem label='手机号' prop='phone'>
<ElInput size='large' v-model={loginForm.phone} placeholder='请输入手机号' />
</ElFormItem>
<ElFormItem label='验证码' prop='code'>
<div class={styles.codeItem}>
<ElInput size='large' v-model={loginForm.code} placeholder='请输入验证码' />
<ElButton size='large' type='primary' class={styles.getBtn}>获取验证码</ElButton>
</div>
</ElFormItem>
<ElFormItem label='密码' prop='password'>
<ElInput size='large' v-model={loginForm.password} show-password placeholder='请输入6~20位密码(字母+数字组合)' />
</ElFormItem>
<ElFormItem>
<ElButton link onClick={goLogin}>已有账号,去登录</ElButton>
</ElFormItem>
<ElFormItem>
<ElButton size='large' type='primary' class={styles.loginBtn} onClick={() => register(ruleForm.value)}>注册</ElButton>
</ElFormItem>
</ElForm>
</div>
</>
})
export default Register
此处可以不需要
**defineComponent**** 但是使用 useRouter() 等方法时会有警告** 》》》 inject() can only be used inside setup() or functional components.
本文由作者按照 CC BY 4.0 进行授权