0.0.3 • Published 2 years ago

tsai-vue-ui v0.0.3

Weekly downloads
-
License
-
Repository
-
Last release
2 years ago

Vite创建项目

  1. yarn create vite
  2. 配置prettier yarn add eslint eslint-plugin-vue --dev
  3. 配置eslint npx eslint --init

Vue 3 + Typescript + Vite

1.inject和provide 1. 使用injectprovide完成属性的透传,后代组件可以改变这个属性的值,更改完,使用到这个属性的组件都会进行更新。 2. react中使用的是context实现的,但是有些不一样,react中的属性和修改这个属性的方法必须同时传递过来,然后进行修改。

vue3组件通信(v3.2.25)

defineProps defineEmits withDefaults 这些函数不用再导入了。

  1. defineProps 是用来接收props的。注意接收来的属性最好不要直接解构!!!

    //bad 这样使用会断开响应式
    const { count } =  defineProps({
        count: {
            type: Number,
            required: true,
        },
    }); 
    
    //good
    const props =  defineProps({
        count: {
            type: Number,
            required: true,
        },
    }); 
    // 这样可以保持响应式,如果需要解构的话要使用toRefs,不使用toRefs的话,也可以直接使用props.count
    const { count } = toRefs(props);
    1. defineProps 两种写法,第一种传统的vue写法,限制类型并且设置默认值是否必须传入等。

      const { count } =  defineProps({
          count: {
              type: Number,
              required: true,
          },
      }); 
      const { count } = toRefs(props);
  1. 第二种ts写法, 借助 withDefaults来设置默认值,使用ts限制类型。

    const props = withDefaults(defineProps<{ count: number }>(), {
        count: 0,
    });
    const { count } = toRefs(props);
  2. defineEmits是用来触发自定义函数的相当于(v2)中的this.$emit()

  3. withDefaults 是用来配置属性默认值的。

1 第一种 使用传统的自定义函数来进行通信

// 父组件
<script setup lang="ts">
import { ref } from 'vue';
import Child from './components/Child.vue';
const count = ref(0);
const changeCount = (p:number) => {
    count.value = p;
}
</script>

<template>
     <Child :count="count" @changeCount ="changeCount"/>
</template>
// 子组件
<script setup lang="ts">
import { toRefs } from 'vue';
// 接收参数使用
const props = defineProps({
    count: {
        type: Number,
        required: true,
    },
});

const { count } = toRefs(props);
// 接收事件
const emmits = defineEmits(['changeCount']);

const change = () => {
     emits('changeCount', count.value++);
};
</script>

<template>
    <h1>{{ count }}</h1>
    <button @click="change">+1</button>
</template>

2 第二种 使用update进行通信

// 父组件
...
<template>
     <Child :count="count" @update:count ="changeCount"/>
</template>
// 子组件
<script setup lang="ts">
...
// 这样来接收事件
const emmits = defineEmits(['update:count']);

const change = () => {
     emits('update:count', count.value++);
};
</script>

3 第三种 使用v-model进行通信

// 父组件 这样写 子组件是第二种update的方式
...
<template>
     <Child v-model:count="count"/>
</template>

ts踩坑

如果使用了eslint可能会出现报错,

  1. 解决defineProps defineEmits withDefaults不引入直接使用会报错
  2. 解决v-model:count="count"报错'v-model' directives require no argument.(vue/no-v-model-argument)
env: {
    'vue/setup-compiler-macros': true,
},
rules: {
    'vue/no-v-model-argument': 'off',
 }

vue3 setup如何使用 inheritAttrs以及如何获取$attrs

  1. <script setup> 可以和普通的 <script> 一起使用。普通的 <script> 在有这些需要的情况下或许会被使用到: 无法在 <script setup> 声明的选项,例如 inheritAttrs 或通过插件启用的自定义的选项。
  1. vue3默认所有的属性都绑定在根元素上,inheritAttrs 可以取消默认绑定,使用useAttrs()可以获取所有的属性。useAttrs()props的区别:props需要声明之后才能取值,并且不包含事件,在props中声明过的属性不会再useAttrs()中出现。
<script lang="ts">
// 普通 <script>, 在模块范围下执行(只执行一次)
// 声明额外的选项
export default {
    inheritAttrs: false, 
    customOptions: {}
}
</script>
<script setup lang="ts">
import {  useAttrs } from 'vue';
// 在 setup() 作用域中执行 (对每个实例皆如此)
// 获取默认原生传入的attrs
const attrs = useAttrs();
const { ...rest } = attrs;
</script>
<!--绑定属性-->
<button v-bind="rest"></button>>

vue3 createApp以及h函数的使用

createApp返回一个提供应用上下文的应用实例。应用实例挂载的整个组件树共享同一个上下文。render可以控制渲染的虚拟dom, h函数就是生成虚拟dom的

import {createApp, h as creatElement} from 'vue';
import Dialog from '@/lib/Dialog.vue';
interface DialogProps {
    title: string | object;
    content: string | object;
    ok?: () => boolean;
    cancel?: () => boolean;
    closeOnClickOverlay?: boolean;
}
export default (props: DialogProps) => {
    const { title, content, ok, cancel, closeOnClickOverlay } = props;
    const divEl = document.createElement('div');
    document.body.appendChild(divEl);
    const handleClose = () => {
        app.unmount();
        divEl.remove();
    };
    const app = createApp({
        render() {
            return creatElement(
                Dialog,
                {
                    visible: true,
                    'onUpdate:visible': (newValue: boolean) => {
                        if (!newValue) {
                            handleClose();
                        }
                    },
                    closeOnClickOverlay,
                    ok,
                    cancel,
                },
                {
                    title: () => title,
                    content: () => content,
                }
            );
        },
    });
    app.mount(divEl);
};

template ref的使用

<template> 
  <div ref="root">This is a root element</div>
 <div v-for="(item, i) in list" :ref="el => { if (el) divs[i] = el }">
    {{ item }}
  </div>
</template>
<script setup>
  import { ref } from 'vue';
  const root = ref(null);
  const divs = ref([]);
  onMounted(() => {
        // DOM 元素将在初始渲染后分配给 ref
        console.log(root.value) // <div>This is a root element</div>
  })
  // 确保在每次更新之前重置ref
  onBeforeUpdate(() => {
        divs.value = []
  })
</script>

teleport

可以把元素传送挂载到特定的位置

<teleport to="#modals">
<div>A</div>
</teleport>
<teleport to="#modals">
<div>B</div>
</teleport>

<!-- result-->
<div id="modals">
<div>A</div>
<div>B</div>
</div>
0.0.3

2 years ago

0.0.2

2 years ago

0.0.1

2 years ago