vue3 jsx写法

3,251 阅读3分钟

1.jsx文件书写格式

jsx内部写<router-view></router-view> 不能生效, 还是要写在vue文件里

写法一: 类似setup script式, 没法传入props

element-plus 在jsx中需要手动引入组件

// Main.jsx
import { defineComponent, ref } from 'vue';
import { ElButton } from "element-plus";
export default defineComponent(() => {
    // 传入 setup 函数
    const status = ref(1)
    const render = () => {
       return <ElButton
          size={"small"}
          color={status === 1 ? "#4bb04e" : "#f99724"}
          style={{ color: "#fff" }}
        >
          {status === 1 ? "已回访" : "未回访"}
        </ElButton>
    };
    return render;
});

写法二: 选项式

// Main.jsx
import { defineComponent, ref } from 'vue';

export default defineComponent({
    name: 'MainPage',
    // 传入组件配置
    props: { name: { type: String, default: '66' } },
    emits: ['update:modelValue'],
    setup(props, { slots, emit, attrs })) {
    
        const handleClick = (value) => {
          emit('update:modelValue', value)
        }
        const render = () => {
            return <p>child {props.name}</p>;
        };
        return render;
    },
});

写法三: 函数式

只能作为组件渲染用, 标签用动态变量会失去响应式

// Main.jsx
function MainPage(props, { slots, emit, attrs }) {
    return <p>child {props.name}</p>;
}

export default MainPage;

调用组件

import Main from '../**/Main';

2. 配置项

安装

pnpm add @vitejs/plugin-vue-jsx vite配置

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

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [vue(), vueJsx()],
})

tsconfig配置

// tsconfig.json
{
    "compilerOptions": {
      "jsx": "preserve",
    }
}

3. 插入样式

引入外联样式

// Main.jsx
import './Main.scss';
function MainPage(props, { slots, emit, attrs }) {
    return (
    <div>
    // 普通类名
    <p class="title">child {props.name}</p>;
    // 动态类名
    <div class={class={activeIndex.value ? 'active nav-item' : 'nav-item'}> </div>
    </div>
    )
}

export default MainPage;

css module方式引入(防止样式污染)

    1. 添加配置
// vite.config.js 或者 vue.config.js 添加css配置
css: {
        // css预处理器
        preprocessorOptions: {
            requireModuleExtension: true,
        },
    },
    1. 修改scss文件名

test.module.scss

    1. 引入方式
import { defineComponent } from 'vue'
import styles from './test.module.scss'

export default defineComponent({
  setup () {
    return () => {
      return <div class={styles.test}>
      </div>
    }
  }
})
    1. 解决ts引入scss报错
// **shims-vue.d.ts**
declare module "*.scss" {
  const classes: { readonly [key: string]: string };
  export default classes;
}
    1. ts类名自动提示工具 a. 安装依赖
npm install typescript-plugin-css-modules --save-dev

b.tsconfig.json添加配置

"plugins": [{"name": "typescript-plugin-css-modules"}]

c. 在项目根目录上创建.vscode文件夹,添加settings.json文件

// settings.json
{
   "typescript.tsdk": "node_modules/typescript/lib",
   "typescript.enablePromptUseWorkspaceTsdk": true
}

4. 基本语法

  • 动态变量

{} 是jsx的万能的用法,里面可以写js的表达式循环逻辑操作等等

<div>{age}</div> //没有" "包裹,统一都是{}
  • v-if
// 使用&&运算
{show && <span>test vif</span>}

// 三元表达式
<div>{ok.value ? <div>yes</div> : <span>no</span>}</div>

// if条件函数
  const vif=()=>{
     if(show) {
        return  <span>test vif</span> 
     }
     return  <span>test velse</span> 
  }   
  return ()=>(   
     <>
        vif()   //if条件函数
     </>
    ) 
  • v-show
<span v-show={show.value}> test vshow</span>
  • v-for
 <nav class="main-nav">
   {tabs.value.map((item) => {
       return <span key={item.id} class="nav-tab">{item.value}</span>;
   })}
 </nav>
  • v-on

使用on+大驼峰形式(首字母大写), 方法名需要使用  {}  包裹起来

无自定义参数的函数不需要带()结尾

jsx需要借助withModifiers,实现.self ,.stop等修饰符的效果

// 标签内部写方法
<span
    onClick={(e) => {
        console.log(e);
    }}
    class="nav-tab"
>
    {item}
</span>

// 方法写在外面
function handleClick (e) {
  console.log(e)
}
<span
    onClick={handleClick}
    class="nav-tab"
>
    {item}
</span>

// 事件传参
function handleClick (item) {
  console.log(item)
}
<span
    onClick={() => handleClick(item)}
    class="nav-tab"
>
    {item}
</span>


//withModifiers包裹vue修饰符 
<div onClick={withModifiers(handleClick, ["stop"])}>{item}</div>
  • ref绑定

ref分两种,一种是指的ref()定义的双向绑定变量,另外则是 绑定在Dom标签的ref引用

ref()定义的双向绑定变量, 加 .value

Dom标签的ref引用, 用ref(null)变量, 不需要加 .value

  const divRef=ref(null);
  const age= ref(0);  
  return ()=>
   (
     <div ref={divRef} > //Dom标签的ref引用
        <span>{age.value}</span>   //ref()双向绑定变量
     </div>
   ) 
  • v-model 语法

组件只有一个v-model时,使用v-model语法

组件只有多个v-model时,可以使用v-model:xx语法

//一个v-model 
<tz-input v-model={age} />
//多个v-model (v-model:修饰符)
<tz-input v-model:foo={age} v-model:bar={gender} />
  • 插槽 v-slots
//方法一
const App = {
  setup() {
    const slots = {
      default: () => <div>A</div>,     //默认插槽
      bar: () => <span>B</span>,       //具名插槽
    };
    return () => <A v-slots={slots} />;
  },
};
//方法二
const App = {
  setup() {
    return () => (
      <>
        <A>
          {{
            default: () => <div>A</div>,   //此方法 默认default不能少
            bar: () => <span>B</span>,   //具名插槽
          }}
        </A>
        <B>{() => "foo"}</B>
      </>
    );
  },
};

v-slots语法 element-plus中table组件scope使用如下

// jsx写法一
<el-table-column
            fixed="right"
            label="操作"
            width="150"
            v-slots={{
              default: (scope: any) => (
                <el-button size="small" onClick={() => handleEdit(scope.row)}>
                  Edit
                </el-button>
              ),
            }}
          ></el-table-column>
jsx写法二
<el-table-column fixed="right" label="操作" width="150">
            {{
              default: (scope: any) => (
                <el-button size="small" onClick={() => handleEdit(scope.row)}>
                  Edit
                </el-button>
              ),
            }}
          </el-table-column>
  • 指令的修饰符

指令使用下划线 ,比如v-loading_fullscreen_lock

<span v-loading_fullscreen_lock={isLoading}> loading </span> 
  • jsx里面引入其他组件
import { defineComponent, ref } from 'vue';
import OrderType from './orderType';
export default defineComponent({
    setup() {
        const render = () => (
            <div>
                <OrderType />
            </div>
        );
        return render;
    },
});