使用vite插件编写tsx文件

一般情况下,我们在template标签里去写静态页面模板。现在可以扩展另一种书写风格 tsx,类似react的jsx语法。vue2 的时候就已经支持jsx写法,只不过不是很友好,随着vue3对typescript的支持度增高,tsx写法越来越被接受。

使用参阅:@vitejs/plugin-vue-jsx

1、安装

npm i @vitejs/plugin-vue-jsx -D

可能会出现插件与vite版本不兼容的问题:

解决办法:添加 --force 参数,强制安装即可。

 

2、配置vite.config.ts

import vueJsx from '@vitejs/plugin-vue-jsx';
// https://vitejs.dev/config/
export default defineConfig({
  plugins: [vueJsx()]
})

3、 配置tsconfig.json

添加以下信息在compilerOptions配置项中:

    "jsx": "preserve",
    "jsxFactory": "h",
    "jsxFragmentFactory": "Fragment",

这样就可以编写tsx文件了。 

4、新建xxx.tsx测试

第一种编写方式,内容如下;

export default function() {

    return (<div>hello world!</div>)
}

像引入组件一样,在App.vue中 import,使用:

import AppTsx from './App'  // 后缀可省略
...
<AppTsx></AppTsx> 

显示结果:

5、使用defineComponent编写tsx

第二种编写方式,该语法类似react的class component书写方式,属于Optional API。

import { defineComponent } from 'vue'
export default defineComponent({
    data () {
        return {
            name: "Tom",
            age: 23
        }
    },
    render () {
        return (<div>{ this.name } is { this.age } years old. </div>)
    }
})

注意:在render函数中使用data函数定义的变量时,用的是单花括号‘{ xxx }’进行渲染。

页面效果:

6、setup函数模式编写tsx

import { defineComponent } from 'vue'
export default defineComponent({
    setup () {
        return () => (<div>Setup!</div>)
    }
 
})

7、指令使用变化

支持使用v-show的指令:

setup () {
        const flag = false
        return () => (<div v-show={flag}>Setup!</div>)
    }

Setup!字样是正常隐藏了的。但如果给变量flag使用ref包装一下,v-show就失效了?如下:

 这是因为在ts里{xx},对于响应式数据的解析不能自动.value拆包,需要手动写上.value。

不支持v-if指令:

解决:采取另一种编程思想(如js的三元表达式):

个人感觉这种结构读性较差。

不支持v-for指令:

采用数组遍历方式渲染,map()代替v-for:

v-bind 可以用 '{}' 替代:

 8、Props接收值

// App.tsc 定义接口类型
type Props = {
    title?:string 
}

export default defineComponent({
    props: {
        title:String
    },
// setup接收props参数
  setup(props:Props) {    
    return () => (
      <>
      <div> Props: { props?.title }</div>
      <hr />
      </>
    );
  }
});
......
// App.vue 传值
<AppTsx title="我是标题"></AppTsx>

结果:

 9、emit派发事件

  ... 
   const fun = () => {
        console.log('click!');        
    }
    return () => (
      <>
     {/* <div onClick={fun()}> Props: { props?.title }</div> */}
         <div onClick={() => fun()}> Props: { props?.title }</div>
      <hr />
      </>
    );
...

不是以@开头的事件书写,注意{xx}不能直接调用函数,它会自动执行,需要改写为回调函数形式:onClick={() => xxx()}。

 传参:

    const fun = (num:number) => {
        console.log('click!', '参数: ', num);        
    }
...
    <div onClick={() => fun(666)}> Props: { props?.title }</div>
...

触发父组件事件:

setup(props:Props, { emit }) {
...
}
...
const fun = (num:number) => {
        console.log('click!', '参数: ', num);   
        emit('on-click', num)     
    }
// App.vue
const getNum = (num:number) => {
  console.log('父组件接收emit: ', num);
}

...
<AppTsx @on-click="getNum" title="我是标题"></AppTsx>
...

10、插槽slots

// 定义一个子组件
const A = (_, { slots }) => (
    <>
      <h1>{ slots.default ? slots.default() : '默认插槽' }</h1>
      <h2>{ slots.foo?.() }</h2>
    </>
  );
...

setup(props:Props, { emit }) {
    const slot = {
        default: () => (<div>hello - default slots</div>),
        foo: () => (<div>world - foo slots</div>),
    }
    return () => (
      <>
      <A v-slots={slot}></A>
      <hr />  
      </>
    );
  }
});
...

 11、表单双向数据绑定

支持v-model指令:

    const v = ref<string>('')
...
    return () => (
      <>
      <input v-model={v.value} type="text" />
      <div>{ v.value }</div>
      </>
    );
...

 

参考: https://xiaoman.blog.csdn.net/article/details/123172735

猜你喜欢

转载自blog.csdn.net/weixin_45719444/article/details/128273146