技术咨询、项目合作、广告投放、简历咨询、技术文档下载 点击这里 联系博主

# vue3 + 组合式 api + typescript 注意事项

# vue3 使用 typescript/tsx 失败

  1. 修改 babel.config.js
module.exports = {
  presets: [
    "@vue/cli-plugin-babel/preset",
    [
      "@babel/preset-env",
      {
        targets: {
          browsers: [
            "last 3 Chrome versions",
            "last 3 Firefox versions",
            "Safari >= 10",
            "Explorer >= 11",
            "Edge >= 12",
          ],
          esmodules: true,
        },
        modules: false,
      },
    ],
  ],
  plugins: ["@vue/babel-plugin-jsx"],
};
  1. 新增shims-vue.d.ts
/* eslint-disable */
declare module '*.vue' {
  import type { DefineComponent } from 'vue'
  const component: DefineComponent<{}, {}, any>
  export default component
}

  1. 新增shims-tsx.d.ts
import Vue, { VNode } from 'vue';

declare global {
  namespace JSX {
    // tslint:disable no-empty-interface
    type Element = VNode;
    // tslint:disable no-empty-interface
    type ElementClass = Vue;
    interface IntrinsicElements {
      [elem: string]: any;
    }
  }
}


  1. 编写 tsx 代码

import { defineComponent } from "vue";
import HelloWorld from "./components/HelloWorld.vue";

export default defineComponent({
  props: {
    message: [String, Function] as PropType<string | (() => string)>,
  },
  setup(props) {
    return () => {
      const message = props.message;
      return (
        <div id="app">
          <img alt="Vue logo" src="./assets/logo.png" width="25%" />
          <HelloWorld msg={typeof message === "string" ? message : message()} />
        </div>
      );
    };
  },
});

# 引入 svg/png 等失败

错误信息:

ERROR in src/views/editor/controller/index.vue:9:22
TS2307: Cannot find module '@/assets/editor/page.png' or its corresponding type declarations.
     7 | import { defineComponent, PropType } from 'vue';
     8 | import CTLItem from './ctl-item';
  >  9 | import PageIcon from '@/assets/editor/page.png';

解决办法:

shims.d.ts中新增:


declare module '*.svg'
declare module '*.png'
declare module '*.jpg'
declare module '*.jpeg'
declare module '*.gif'
declare module '*.bmp'
declare module '*.tiff'

# vue 中如何修改 svg 颜色

  1. 编写 svg 组件
import { defineComponent } from "vue";
export default defineComponent({
  setup(props, { emit }) {
    return () => (
      <svg
        class="svg-icon"
        viewBox="0 0 1024 1024"
        version="1.1"
        xmlns="http://www.w3.org/2000/svg"
        p-id="3141"
        width="40"
        onClick={() => {
          emit("click");
        }}
      >
        <defs>
          <style type="text/css"></style>
        </defs>
        <path
          d="M236.864 64h472.96L896 261.12V848c0 61.856-54.72 112-114.848 112h-544.32C176.768 960 128 909.856 128 848V176c0-61.856 48.736-112 108.864-112zM672 128v133.856A26.144 26.144 0 0 0 698.144 288H832L672 128z m106.656 768c29.44 0 53.344-24.576 53.344-54.848V347.424H672c-29.44 0-53.344-24.544-53.344-54.848V128H245.344C215.904 128 192 152.576 192 182.848v658.304C192 871.424 215.872 896 245.344 896h533.312z"
          p-id="3142"
        ></path>
      </svg>
    );
  },
});
  1. 修改fill属性
.svg-icon {
  &:hover {
    fill: var(--xpage-mis--color-primary);
    background-color: var(--xpage-mis-sidebar-hover-bg-colo);
  }
}

# vue 常用指令 tsx/jsx 的实现

# v-bind

绑定标签属性。

注意点

  1. 属性的写法上和 HTML 存在区别,在写 JSX 的时候,所有的属性都是驼峰式的写法.如:className. 有些属性名不能直接绑定,如:for、class。for-> className for-> htmlFor
  2. data-* 和 aria-* 两类属性是和 HTML 一致的 data 系列是指自定义数据。 aria 系列是指一般是为不方便的人士提供的功能。

例 1

// 绑定span的title。
// 在jsx中没有必要要用ref,我就是说明一下可以这么用。
import { ref } from "vue";
export default () => {
  const msg = ref("小火汁😂");
  return <span title={msg.value}>走成华大道(鼠标停一哈看提示)</span>;
};

例 2

const placeholderText = "email";
const App = () => <input type="email" placeholder={placeholderText} />;

# v-show

const App = defineComponent({
  data() {
    return { visible: true };
  },
  render() {
    return <input v-show={this.visible} type="text" placeholder="7777" />;
  },
});
export default App;

# v-model

注意:如果想要使用参数,可以用一个参数, 但是如果用了两个参数,第二个参数需要为字符串!以作为参数名。 官方readme

<input v-model={val} />
<input v-model={[val, ["modifier"]]} />

<A v-model={[val, "argument", ["modifier"]]} />;
//会变编译成:
h(A, {
  argument: val,
  argumentModifiers: {
    modifier: true,
  },
  "onUpdate:argument": ($event) => (val = $event),
});

# v-models 传递多个参数

注意: 你应该传递一个二维数组给 v-models。

<A v-models={[[foo], [bar, "bar"]]} />
<A
  v-models={[
    [foo, "foo"],
    [bar, "bar"],
  ]}
/>
<A
  v-models={[
    [foo, ["modifier"]],
    [bar, "bar", ["modifier"]],
  ]}
/>;
//会变编译成:
h(A, {
  modelValue: foo,
  modelModifiers: {
    modifier: true,
  },
  "onUpdate:modelValue": ($event) => (foo = $event),
  bar: bar,
  barModifiers: {
    modifier: true,
  },
  "onUpdate:bar": ($event) => (bar = $event),
});

# 插槽

注意: 在 jsx/tsx 中,应该使用 v-slots 代替 v-slot

const A = (props, { slots }) => (
  <>
    <h1>{slots.default ? slots.default() : "foo"}</h1>
    <h2>{slots.bar?.()}</h2>
  </>
);

const App = {
  setup() {
    const slots = {
      bar: () => <span>B</span>,
    };
    return () => (
      <A v-slots={slots}>
        <div>A</div>
      </A>
    );
  },
};

// or

const App = {
  setup() {
    const slots = {
      default: () => <div>A</div>,
      bar: () => <span>B</span>,
    };
    return () => <A v-slots={slots} />;
  },
};

// or
const App = {
  setup() {
    return () => (
      <>
        <A>
          {{
            default: () => <div>A</div>,
            bar: () => <span>B</span>,
          }}
        </A>
        <B>{() => "foo"}</B>
      </>
    );
  },
};

# 使用 provide/inject

  1. 封装公共的 provide/inject
import { provide, inject } from "vue";
const EDITOR_PROVIDE = "editor";

export type EditorProvideType = {
  currentCmp: any;
  changeCurrentCmp?: (schema: any) => void;
};

/**
 * 最外层组件暴露实例给下面的子组件
 * @param state
 */
export function provideEditor(state: EditorProvideType): void {
  provide<EditorProvideType>(EDITOR_PROVIDE, state);
}

/**
 * 子组件获取顶层父组件提供的实例方法
 * @returns
 */
export function injectEditor(): EditorProvideType | undefined {
  return inject<EditorProvideType>(EDITOR_PROVIDE);
}
  1. 父组件 provide

 setup() {
    // 暴露实例给子组件
    const state = reactive<EditorProvideType>({
      currentCmp: null,
      changeCurrentCmp(schema: XPageUISchemaType) {
        state.currentCmp = schema;
      },
    });
    provideEditor(state);

    return {
      ...toRefs(state),
    };
  },

  1. 子组件 inject

  setup() {
    const state = reactive<{
      list: any[];
    }>({
      list: [],
    });
    // inject需要在setup中
    const editor = injectEditor();

    return {
      onWidgetAdd: (evt: SortableEvent) => {
        // 记得在这里更新一下数据
        if (evt.newIndex !== undefined) {
          editor?.changeCurrentCmp?.(state.list[evt.newIndex]);
        }
      }
    };
  },
【未经作者允许禁止转载】 Last Updated: 2/4/2024, 6:06:40 AM