自学内容网 自学内容网

17 vue3之tsx&手写vite tsx插件

我们之前呢是使用Template去写我们模板。现在可以扩展另一种风格TSX风格

vue2 的时候就已经支持jsx写法,只不过不是很友好,随着vue3对typescript的支持度,tsx写法越来越被接受,减少我们学习react的成本 Ant Design组件库就是使用tsx语法编写的

安装插件

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

vite.config.ts配置 

import vueJsx from "@vitejs/plugin-vue-jsx";

export default ({ mode }: any) => {
  console.log("mode===>", mode);
  console.log(loadEnv(mode, process.cwd()));
  return defineConfig({
    plugins: [
      vue(),
      vueJsx(), //注册
      AutoImport({
        imports: ["vue"], // 引入vue的自动引入
      }),
    ],
  });
};

 修改tsconfig.json 配置文件

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

使用Tsx

在目录新建一个xxxxxx.tsx文件

tsx支持 v-model 的使用

 
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

 
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是不支持 可使用三元表达式支持

import { ref } from 'vue'
 
let flag = ref(false)
 
const renderDom = () => {
    return (
        <>
            {
                flag.value ? <div>景天</div> : <div>雪见</div>
            }
        </>
    )
}
 
export default renderDom

v-for不支持 可使用map支持

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使用

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开头
  • 所有事件名称首字母大写
 
const renderDom = () => {
    return (
        <>
            <button onClick={clickTap}>点击</button>
        </>
    )
}
 
const clickTap = () => {
    console.log('click');
}
 
export default renderDom

Props 接受值

 
import { ref } from 'vue'
 
type Props = {
    title:string
}
 
const renderDom = (props:Props) => {
    return (
        <>
            <div>{props.title}</div>
            <button onClick={clickTap}>点击</button>
        </>
    )
}
 
const clickTap = () => {
    console.log('click');
}
 
export default renderDom

Emit派发

type Props = {
    title: string
}
 
const renderDom = (props: Props,content:any) => {
    return (
        <>
            <div>{props.title}</div>
            <button onClick={clickTap.bind(this,content)}>点击</button>
        </>
    )
}
 
const clickTap = (ctx:any) => {
 
    ctx.emit('on-click',1)
}

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 you can use object slots when `enableObjectSlots` is not false.
const App = {
  setup() {
    return () => (
      <>
        <A>
          {{
            default: () => <div>A</div>,
            bar: () => <span>B</span>,
          }}
        </A>
        <B>{() => "foo"}</B>
      </>
    );
  },
};

完整示例代码

三种不同写法的tsx语法

三种不同写法的tsx语法 一和3的方式用的比较多 我们这里主要是使用第三种

  • 第一种返回渲染函数
  • 第二种optionsApi方式

  • 第三种setup函数模式

// 三种不同写法的tsx语法 一和3的方式用的比较多 我们这里主要是使用第三种
// 第一种返回渲染函数
/* export default function () {
  return <div>cookie</div>;
} */

// 第二种optionsApi方式

/*import { defineComponent } from "vue";
 export default defineComponent({
  data() {
    return {
      name: "cookie123",
    };
  },
  render() {
    return <div>{this.name}</div>;
  },
}); */

//第三种setup函数模式
/* import { defineComponent } from "vue";
export default defineComponent({
  setup() {
    return () => <div>cookie-setup</div>;
  },
}); */

父组件

<template>
  <div class=""></div>
  <Cookie :title="'Cookie标题'" @cusemit="getStr"></Cookie>
  <hr />
  <MyTSX title="MyTSX标题" @emit1="getStr"></MyTSX>
</template>

<script setup lang="ts">
import { ref, reactive } from "vue";
import MyTSX from "./components/MyTSX";
import Cookie from "./components/Cookie ";
let getStr = (params: string) => {
  console.log("a接收,,,", params);
};
</script>

<style lang="less" scoped></style>

子组件MyTSX.tsx

  • 派发事件注意函数柯里化
// 三种不同写法的tsx语法 一和3的方式用的比较多 我们这里主要是使用第三种
// 第一种返回渲染函数
/* export default function () {
  return <div>cookie</div>;
} */

// 第二种optionsApi方式

/*import { defineComponent } from "vue";
 export default defineComponent({
  data() {
    return {
      name: "cookie123",
    };
  },
  render() {
    return <div>{this.name}</div>;
  },
}); */

//第三种setup函数模式
/* import { defineComponent } from "vue";
export default defineComponent({
  setup() {
    return () => <div>cookie-setup</div>;
  },
}); */

// v-show 指令
// 1.ref在tsx语法中变量中使用{flag.vue},并且值不会如在template中自动解析.value
// 2.在tsx语法中,v-if不支持可使用三元表达式代替
// v-for也是不支持的,需要使用map函数代替
// v-bind直接使用name={}  <div name="666">name</div>
// props emit  <button onClick={fn()}>点击</button>还未点击就触发了 需要使用函数柯里化的方式处理
// slot插槽
import { defineComponent, ref } from "vue";
type Props = {
  // 泛型字面量
  title?: string;
};
// 定义一个组件

const A = (props, { slots }) => (
  <div>
    <div>{slots.default ? slots.default() : "默认值"}</div>
    {/* 定义其他的插槽 slots.bar?.()等同上面的写法 */}
    <div>{slots.bar?.()}</div>
  </div>
);
export default defineComponent({
  props: { title: String },
  emits: ["cusemit"],
  setup(props: Props, { emit }) {
    let show = ref(true);
    let arr = [1, 2, 3, 4, 5];
    let name = "666";
    const fn = (a: any) => {
      console.log("fn触发了", a);
      emit("cusemit", a);
    };
    const slot = {
      default: () => <div>default插槽值</div>,
      bar: () => <div>bar插槽值</div>,
    };
    return () => (
      <div>
        <div v-show={show.value}>show</div>
        {show ? <div>显示1</div> : <div>显示0</div>}
        {arr.map((v) => {
          return <div>${v}</div>;
        })}
        <div name={name}>name</div>
        <hr />
        <h3>props emit 语法</h3>
        <div>{props?.title}</div>
        <button onClick={() => fn(33)}>点击</button>
        <hr />
        <h3>插槽 语法</h3>
        <A v-slots={slot} />
      </div>
    );
  },
});

子组件cookie.tsx 与MyTSX.tsx不同的写法

import { ref } from "vue";
/* 
需要注意的点
1.ref在tsx语法中变量中使用{flag.vue},并且值不会如在template中自动解析.value

*/

let v = ref<string>("");
let flag = ref(false);
let list = [1, 2, 3];

type Props = {
  // 泛型字面量
  title: string;
};

const renderDom = (props: Props, ctx: any) => {
  // ctx东西
  //  1.v-model
  /*return (
    <>
      <input v-model={v.value} type="text" />
      <div>{v.value}</div>
    </>
  ); */

  //2.v-show ,v-if不支持可以使用js编程的方式去转变
  /* return (
    <div>
      <div v-show={flag}>显示1</div>
      <div v-show={!flag}>显示2</div>
      {flag ? <div>显示3</div> : <div>显示4</div>}
    </div>
  ); */

  //3.v-for不支持,可以用map ,v-bind不支持可以用data-index,v-on不支持可以用onClick={tap}  传参使用onClick={tap1.bind(this, 66)}
  // props在组件中使用的是一样的,事件派发ctx
  return (
    <div>
      <div>{props.title}</div>
      {list.map((v) => {
        return (
          <div onClick={tap} data-index={v}>
            ${v}
          </div>
        );
      })}
      <button onClick={tap1.bind(this, 66)}>
        函数传参,请点击
      </button>
      <button onClick={tap2.bind(this, ctx)}>
        派发事件,请点击
      </button>
    </div>
  );
};
let tap = () => {
  console.log("click");
};
let tap1 = (v: number) => {
  console.log(v);
};
let tap2 = (ctx: any) => {
  console.log(ctx);
  ctx.emit("emit1", "发送");
};

export default renderDom;

效果图:

18 vue3之自动引入ref插件&深入使用v-model-CSDN博客TIps 在Vue3 v-model 是破坏性更新的v-model在组件里面也是很重要的v-model 其实是一个语法糖 通过props 和 emit组合而成的默认值的改变prop:value -> modelValue;事件:input -> update:modelValue;v-bind 的 .sync 修饰符和组件的 model 选项已移除新增 支持多个v-model新增 支持自定义 修饰符 Modifiershttps://blog.csdn.net/qq_37550440/article/details/142522527?sharetype=blogdetail&sharerId=142522527&sharerefer=PC&sharesource=qq_37550440&spm=1011.2480.3001.8118


原文地址:https://blog.csdn.net/qq_37550440/article/details/142515947

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!