vue中使用jsx

发布时间 2023-04-14 16:55:24作者: 丁少华

前言

相对来说 有些时候用jsx更合适,更灵活些

安装依赖

有对应的包支持

yarn add --dev @vitejs/plugin-vue-jsx

配置插件

在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({})
});

使用

ant的左侧导航,vue的模板语法写法就体验很糟糕,这里我将其改为jsx模式。

import { computed, defineComponent, resolveComponent, h  } from "vue";
import { useStore } from "/@/store";
import { useRoute } from "vue-router";
import logoImg from "/@/assets/logo.png";
import styled from "@magister_zito/vue3-styled-components";
import router from "/@/router";

const StyledLogo = styled.div`
  height: 32px;
  margin: 16px;
  background: rgba(255, 255, 255, 0.3);
  color: white;
  display: flex;
  align-items: center;
  justify-content: center;
  font-weight: 600;
  font-size: 18px;
  img {
    height: 32px;
    margin-right: 10px;
  }
`;

const toMenu = (menu: any) => {
  router.push(menu.path);
};

const SubMenu = defineComponent({
  props: {
    menuInfo: {
      type: Object,
      default: "请输入",
    },
  },
  setup(props) {
    return () => (
      <a-sub-menu
        key={props.menuInfo.path}
        v-slots={{
          title: () => <span>{props.menuInfo.title}</span>,
          icon: () =>  h(resolveComponent(props.menuInfo.meta.icon))
        }}
      >
        {props.menuInfo.children.map((item: any) =>
          item.children ? (
            <SubMenu menu-info={item} key={item.path} />
          ) : (
            <a-menu-item
              key={item.path}
              onClick={() => {
                toMenu(item);
              }}
            >
              {item.title}
            </a-menu-item>
          )
        )}
      </a-sub-menu>
    );
  },
});



export default defineComponent({
  name:'LayoutSider',
  setup() {
    const route = useRoute();
    const store = useStore();

    // 当前高亮的选中菜单
    const selectedKeys = computed<string[]>(() => {
      return [route.path];
    });

    // 处理刷新后 显示的二级菜单或者三级菜单
    const openKeys = computed<string[]>(() => {
      let arr = [];
      arr = route.path.split("/").splice(1, route.path.split("/").length);
      arr = arr.map((item) => {
        item = "/" + item;
        return item;
      });
      return arr;
    });

    return () => (
      <a-layout-sider collapsed={store.openMenu}>
        <StyledLogo>
          <img src={logoImg} />
          { !store.openMenu && <span>Ant Design</span>}
        </StyledLogo>
        <a-menu
          style="width: auto !important"
          v-model:openKeys={openKeys.value}
          v-model:selectedKeys={selectedKeys.value}
          mode="inline"
          theme="dark"
        >
          {store.siteInfo.menus.map((item: any) =>
            item.children ? (
              <SubMenu key={item.path} menuInfo={item} />
            ) : (
              <a-menu-item
                key={item.path}
                onClick={() => {
                  toMenu(item);
                }}
                v-slots={{
                  icon: () =>  h(resolveComponent(item.meta.icon))
                }}
              >
                {item.title}
              </a-menu-item>
            )
          )}
        </a-menu>
      </a-layout-sider>
    );
  },
});

其它

如上 也看到了 如果不像样式分离,我也可以使用 styled 方案,即css in js