弑君者

V1

2022/08/05阅读:12主题:默认主题

Vue3 + setup + ts 使用总结

阅读vue的英文官网

中文的vue官网比vue的英文官网差很多,不管学什么都要去获取第一手资料,不要看中文官网,直接去看英文官网!!!

根据自己的使用习惯,设置vscode的vue代码片段,推荐使用https://snippet-generator.app

"vue3模版": {

"prefix""vue3",

"body": [

"<template>",

" <div class='${1:box}'></div>",

"</template>",

" ",

"<script setup lang='ts'>",

" import {ref,reactive} from \"vue\";",

" ${3}",

"</script>",

" ",

"<style lang=\"scss\" scoped>",

" .${2:box} {",

" }",

"</style>"

],

"description""vue3模版"

}

组件引入

当使用setup的时候,组件直接引入就可以了,不需要再自己手动注册

ref和reactive

ref一般用于基本的数据类型,比如string,boolean reactive一般用于对象 ref的地方其实也是调用的reactive实现的。

子组件传父组件

子组件

<template>

<div class="child"></div>

</
template>


<script setup lang="ts">

import { ref, reactive } from "vue";

function doSth({

console.log(333);

}

defineExpose({ doSth });

</script>


<style lang="scss" scoped>

.child {

}

</
style>

父组件

<template>

<div class="father" @click="doSth1">222</div>

<Child ref="childRef"></
Child>

</template>

<script setup lang="ts">

import { ref, reactive } from "vue";

import Child from "./
Child.vue";

const childRef = ref();

function doSth1() {

childRef.value.doSth();

}

</script>

<style lang="
scss" scoped>

.father {

}

</style>

父组件传子组件

父组件

<template>

<div class="father"></div>

<Child @click="doSth"></
Child>

</template>

<script setup lang="ts">

import { ref, reactive } from "vue";

import Child from "./
Child.vue";

function doSth() {

console.log(112);

}

</script>

<style lang="
scss" scoped>

.father {

}

</style>

子组件

<template>

<div class="child">2222</div>

</
template>

<script setup lang="ts">

import { ref, reactive, onMounted } from "vue";

const emits = defineEmits(["doSth"]);

onMounted(() => {

emits("doSth");

});

</script>

<style lang="scss" scoped>

.child {

}

</
style>

toRefs

当从父组件向子组件传props的时候,必须使用toRefs或者toRef进行转一下,这是为什么呢?

这里是因为如果不使用toRefs转一次的话,当父组件中的props改变的时候,子组件如果使用了Es6的解析,会失去响应性。

可以看下如下例子

父组件

<template>

<div class="father" @click="changeVal">{{ fatherRef }}</div>

<Child :fatherRef="fatherRef"></
Child>

</template>

<script setup lang="ts">

import { ref, reactive } from "vue";

import Child from "./
Child.vue";

const fatherRef = ref(1);

function changeVal() {

fatherRef.value = 2;

}

</script>

<style lang="
scss" scoped>

.father {

margin-bottom: 40px;

}

</style>

子组件

<template>

<div class="child" @click="changeVal">{{ fatherRef }}</div>

</
template>

<script setup lang="ts">

import { ref, reactive, onMounted, toRefs } from "vue";

const props = defineProps<{

fatherRef: any;

}>();

const { fatherRef } = props;

function changeVal({

fatherRef.value = 34;

}

</script>

<style lang="scss" scoped>

.child {

}

</
style>

可以看到当父组件如果点击之后,因为使用const { fatherRef } = props;进行解析,就失去了响应性

所以当父组件变成2的时候,子组件还是1。

这里有两种解决办法

  1. 使用const { fatherRef } = toRefs(props);
  2. 在模版中中使用props.fatherRef

子组件使用v-model

可以在子组件中使用computed,实现双向绑定

父组件

<template>

<div class="father">{{ fatherRef }}</div>

<Child :fatherRef="fatherRef" @changeVal="changeVal"></
Child>

</template>

<script setup lang="ts">

import { ref } from "vue";

import Child from "./
Child.vue";

const fatherRef = ref("
1");

function changeVal(val: string) {

fatherRef.value = val;

}

</script>


<style lang="
scss" scoped>

.father {

margin-top: 40px;

margin-bottom: 40px;

}

</style>

子组件

<template>

<!-- <div class="child">{{ props.fatherRef }}</div> -->

<input type="text" v-model="inputVal" /
>

</template>

<script setup lang="ts">

import { computed } from "vue";

const props = defineProps<{

fatherRef: string;

}>();

const emits = defineEmits(["changeVal"]);


const inputVal = computed({

get() {

return props.fatherRef;

},

set(val: string) {

emits("changeVal", val);

},

});

</
script>

<style lang="scss" scoped>

.child {

}

</style>

可以从父组件传递值和改变值的方法,然后子组件也可以使用v-model

例子中父组件传递 modelValue和update:modelValue方法 父组件:

<template>

<Child :modelValue="searchText" @update:modelValue="changeVal"> </Child>

</
template>

<script setup lang="ts">

import { ref } from "vue";

import Child from "./Child.vue";

const searchText = ref(1);

function changeVal(val: number{

searchText.value = val;

}

</script>

<style lang="scss" scoped>

.father {

margin-top: 40px;

margin-bottom: 40px;

}

.btn {

font-size: 20px;

color: red;

}

</
style>

子组件:

<template>

<!-- <div class="child">{{ props.fatherRef }}</div> -->

<!-- <div v-bind="attrs">

<slot name="test1">11</
slot>

<input type="text" v-model="inputVal" />

</div> -->

<input v-model="modelValue" /
>

</template>


<script setup lang="ts">

import { computed, useAttrs, useSlots } from "vue";

const props = defineProps<{

modelValue: number;

}>();

/
/ const emits = defineEmits(["changeVal"]);

</
script>


<style lang="scss" scoped>

.child {

}

</style>

使用useAttrs和useSlots

useAttrs 可以获取父组件传过来的id和class等值。 useSlots 可以获得插槽的内容。 例子中,我们使用useAttrs获取父组件传过来的id和class,useSlots获取插槽的内容。

父组件:

<template>

<div class="father">{{ fatherRef }}</div>

<Child :fatherRef="fatherRef" @changeVal="changeVal" class="btn" id="111">

<template #test1>

<div>1223</
div>

</template>

</
Child>

</template>

<script setup lang="ts">

import { ref } from "vue";

import Child from "./
Child.vue";

const fatherRef = ref("
1");

function changeVal(val: string) {

fatherRef.value = val;

}

</script>

<style lang="
scss" scoped>

.father {

margin-top: 40px;

margin-bottom: 40px;

}

.btn {

font-size: 20px;

color: red;

}

</style>

子组件:

<template>

<!-- <div class="child">{{ props.fatherRef }}</div> -->

<div v-bind="attrs">

<slot name="test1">11</
slot>

<input type="text" v-model="inputVal" />

</div>

</
template>

<script setup lang="ts">

import { computed, useAttrs, useSlots } from "vue";

const props = defineProps<{

fatherRef: string;

}>();

const emits = defineEmits(["changeVal"]);

const slots = useSlots();

const attrs = useAttrs();

console.log(122, attrs, slots);

const inputVal = computed({

get() {

return props.fatherRef;

},

set(val: string) {

emits("changeVal", val);

},

});

</script>


<style lang="scss" scoped>

.child {

}

</
style>

分类:

前端

标签:

Vue.js

作者介绍

弑君者
V1