当前位置: 首页 > article >正文

vue3入门知识(二)

computed

计算属性是有缓存的,方法没有缓存

计算属性得到的数据是一个ref定义的响应式数据

<template>
    <div class="person">
        姓:<input type="text" v-model="firstName"><br>
        名:<input type="text" v-model="lastName"><br>
        全名:<span>{{ fullName }}</span><br>
        <button @click="changeFullName">修改名字</button>
    </div>
</template>

<script setup lang="ts" name="Person"> 
import { ref, computed } from 'vue';

let firstName = ref('张');
let lastName = ref('三');

// 这样定义的计算属性是只读的
// let fullName = computed(() => {
//     return firstName.value + '-' + lastName.value;
// });

// 这样定义的计算属性是可读可写的
let fullName = computed({
    get() {
        return firstName.value + '-' + lastName.value;
    },
    set(newValue) {
        const names = newValue.split('-');
        firstName.value = names[0];
        lastName.value = names[1];
    }
});

function changeFullName() {
    fullName.value = '李-四';
};
</script>

watch

监视数据的变化,vue3中watch只能监视以下四种数据:

1. ref定义的数据

2. reactive定义的数据

3. 函数返回一个值(getter函数)

4. 一个包含上述内容的数组

1. 监视ref定义的【基本类型】数据:直接写数据名即可,监视的是其value值的改变

<template>
    <div class="person">
        <h2>当前求和为:{{ sum }}</h2>
        <button @click="changeSum">点我sum+1</button>
    </div>
</template>

<script setup lang="ts" name="Person"> 
import { ref, watch } from 'vue';

let sum = ref(0);

// const stopWatch = watch(sum, (newVal, oldVal) => {
//     console.log('sum.value changed: ', newVal, oldVal);
//     if (newVal > 10) {
//         // 当 sum 大于10时,取消监听
//         stopWatch();
//     }
// });

watch(sum, (newVal, oldVal) => {
    console.log('sum.value changed: ', newVal, oldVal);
});

function changeSum() {
    sum.value++;
};
</script>

2. 监视ref定义的【对象类型】数据:直接写数据名,监视的是对象的【地址值】,若想监视对象内部的数据,要手动开启深度监视

<template>
    <div class="person">
        <h2>姓名:{{ person.name }}</h2>
        <h2>年龄:{{ person.age }}</h2>
        <button @click="changeName">修改姓名</button>
        <button @click="changeAge">修改年龄</button>
        <button @click="changePerson">修改</button>
    </div>
</template>

<script setup lang="ts" name="Person"> 
import { ref, watch } from 'vue';

let person = ref({
    name: '张三',
    age: 18,
});

// watch的第一个参数是:被监视的数据
// watch的第二个参数是:监视的回调函数
// watch的第三个参数是:配置对象(deep、immediate等)

// 监视的是对象的地址值
// watch(person, (newVal, oldVal) => {
//     console.log('person changed', newVal, oldVal);
// });

// 监视对象内部属性的变化 手动开启深度监听 立即执行 immediate: true
watch(person, (newVal, oldVal) => {
    // 当对象整体被替换时 newVal 和 oldVal 不同
    // 当对象中某个属性被修改 newVal 和 oldVal 相同
    console.log('person changed', newVal, oldVal);
}, { deep: true });

function changeName() {
    person.value.name += '~';
};
function changeAge() {
    person.value.age++;
};
function changePerson() {
    person.value = {
        name: '李四',
        age: 80,
    };
}
</script>

<style scoped lang="less">
.person {
    button {
        margin: 0 10px;
    }
}
</style>

3. 监视reactive定义的【对象类型】数据,且默认开启了深度监视

<template>
    <div class="person">
        <h2>姓名:{{ person.name }}</h2>
        <h2>年龄:{{ person.age }}</h2>
        <button @click="changeName">修改姓名</button>
        <button @click="changeAge">修改年龄</button>
        <button @click="changePerson">修改</button>
    </div>
</template>

<script setup lang="ts" name="Person"> 
import { reactive, watch } from 'vue';

let person = reactive({
    name: '张三',
    age: 18,
});

// 监视【reactive】定义的【对象类型】数据 默认是开启深度监听的 且无法关闭
watch(person, (newVal, oldVal) => {
    // newVal 和 oldVal 相同 因为修改时操作的是同一个对象
    console.log('person changed', newVal, oldVal);
});

function changeName() {
    person.name += '~';
};
function changeAge() {
    person.age++;
};
function changePerson() {
    Object.assign(person, {
        name: '李四',
        age: 80,
    });
}
</script>

<style scoped lang="less">
.person {
    button {
        margin: 0 10px;
    }
}
</style>

4. 监视ref或reactive定义的【对象类型】数据中的某个属性

(1)若该属性不是【对象类型】,需要写成函数形式

(2)若该属性依然是【对象类型】,可直接写,也可写成函数,建议写成函数

<template>
    <div class="person">
        <h2>姓名:{{ person.name }}</h2>
        <h2>年龄:{{ person.age }}</h2>
        <h2>汽车:{{ person.car.c1 }}、{{ person.car.c2 }}</h2>
        <button @click="changeName">修改姓名</button>
        <button @click="changeAge">修改年龄</button>
        <button @click="changeC1">修改第一台车</button>
        <button @click="changeC2">修改第二台车</button>
        <button @click="changeCar">修改整个车</button>
    </div>
</template>

<script setup lang="ts" name="Person"> 
import { reactive, watch } from 'vue';

let person = reactive({
    name: '张三',
    age: 18,
    car: {
        c1: '奔驰',
        c2: '宝马',
    },
});

// 监视响应式对象中的某个属性 且该属性是基本类型的 要写成函数式
watch(() => { return person.name }, (newVal, oldVal) => {
    // newVal 和 oldVal 不同
    console.log('person.name changed', newVal, oldVal);
});

// 监视响应式对象中的某个属性 且该属性是对象类型的 建议写成函数式否则整体修改时监听不到 需要加深度监听
watch(() => { return person.car }, (newVal, oldVal) => {
    // newVal 和 oldVal 不同
    console.log('person.car changed', newVal, oldVal);
}, { deep: true });

function changeName() {
    person.name += '~';
};
function changeAge() {
    person.age++;
};
function changeC1() {
    person.car.c1 = '奥迪';
};
function changeC2() {
    person.car.c2 = '保时捷';
};
function changeCar() {
    person.car = {
        c1: '11',
        c2: '22',
    };
};
</script>

<style scoped lang="less">
.person {
    button {
        margin: 0 10px;
    }
}
</style>

5. 监视响应式对象中的某几个属性

<template>
    <div class="person">
        <h2>姓名:{{ person.name }}</h2>
        <h2>年龄:{{ person.age }}</h2>
        <h2>汽车:{{ person.car.c1 }}、{{ person.car.c2 }}</h2>
        <button @click="changeName">修改姓名</button>
        <button @click="changeAge">修改年龄</button>
        <button @click="changeC1">修改第一台车</button>
        <button @click="changeC2">修改第二台车</button>
        <button @click="changeCar">修改整个车</button>
    </div>
</template>

<script setup lang="ts" name="Person"> 
import { reactive, watch } from 'vue';

let person = reactive({
    name: '张三',
    age: 18,
    car: {
        c1: '奔驰',
        c2: '宝马',
    },
});

// 监视响应式对象中的某几个属性
watch([() => { return person.name }, () => { return person.car.c1 }], (newVal, oldVal) => {
    console.log('person.car changed', newVal, oldVal);
}, { deep: true });

function changeName() {
    person.name += '~';
};
function changeAge() {
    person.age++;
};
function changeC1() {
    person.car.c1 = '奥迪';
};
function changeC2() {
    person.car.c2 = '保时捷';
};
function changeCar() {
    person.car = {
        c1: '11',
        c2: '22',
    };
};
</script>

<style scoped lang="less">
.person {
    button {
        margin: 0 10px;
    }
}
</style>

watchEffect

立即执行一个函数,同时响应式地追踪其依赖,并在依赖更改时重新执行该函数

watch 和 watchEffect 对比:

1. 都能监听响应式数据的变化,监听数据变化的方式不同

2. watch:要明确指出监视的数据

3. watchEffect:不用明确指出监视的数据(其中用到哪些数据就监视哪些属性)

<template>
    <div class="person">
        <h2>当前水温:{{ temp }}度</h2>
        <h2>当前水位:{{ height }}cm</h2>
        <button @click="changeTemp">水温+10</button>
        <button @click="changeHeight">水位+10</button>
    </div>
</template>

<script setup lang="ts" name="Person"> 
import { ref, watch, watchEffect } from 'vue';

const temp = ref(10);
const height = ref(0);

// watch([temp, height], (newVal) => {
//     const [t, h] = newVal;
//     if(t >= 60 || h >= 80) {
//         console.log('发送请求');
//     }
// });

watchEffect(() => {
    // 会立即执行一次
    console.log('执行了');
    if(temp.value >= 60 || height.value >= 80) {
        console.log('发送请求');
    }
});

function changeTemp() {
    temp.value += 10;
};
function changeHeight() {
    height.value += 10;
};
</script>

<style scoped lang="less">
.person {
    button {
        margin: 0 10px;
    }
}
</style>

标签的ref

1. 用在普通DOM标签上,获取的是DOM节点

2. 用在组件标签上,获取的是组件实例对象

// 父组件
<template>
    <h2>中国</h2>
    <h2 ref="title2">北京</h2>
    <h2>朝阳</h2>
    <button @click="showLog">输出</button>
    <Person ref="ren"></Person>
</template>

<script lang="ts" setup name="App">
import Person from './components/Person.vue';
import { ref } from 'vue';

const title2 = ref();
const ren = ref();

function showLog() {
    // console.log(title2.value); // 输出html标签
    console.log(ren.value); // 输出组件实例
}
</script>
// 子组件
<template>
    <div class="person"></div>
</template>

<script setup lang="ts" name="Person"> 
import { ref, defineExpose } from 'vue';

const a = ref(0);
const b = ref(1);
const c = ref(2);

// 在这里暴露出去的值 父组件才可以拿到
defineExpose({a, b});
</script>

 接口、自定义类型、泛型

// src/types/index.ts
// 定义一个接口 用于限制person对象的具体属性
export interface PersonInter {
    name: string,
    age: number,
    id: string,
};

// 一个自定义类型
// export type Persons = Array<PersonInter>; // 泛型
export type Persons = PersonInter[];
<template>
    <div class="person"></div>
</template>

<script setup lang="ts" name="Person">
import { type PersonInter, type Persons } from '@/types';

const person:PersonInter = {
    name: '张三',
    age: 18,
    id: '1',
};

const persons:Array<PersonInter> = [
    {
        name: '张三',
        age: 18,
        id: '1',
    },
    {
        name: '李四',
        age: 18,
        id: '2',
    },
];

const personList:Persons = [
    {
        name: '张三',
        age: 18,
        id: '1',
    },
    {
        name: '李四',
        age: 18,
        id: '2',
    },
];
</script>

组件通信--父传子

<template>
    <div class="person">
        <!-- <h2>{{ a }}</h2> -->
        <!-- <h2>{{ list }}</h2> -->
        <ul>
            <li v-for="item in list" :key="item.id">
                {{ item.name }} -- {{ item.age }}
            </li>
        </ul>
    </div>
</template>

<script setup lang="ts" name="Person">
// defineProps不用引入也可以使用
// 在vue3中 defineXXX 叫作宏函数 不用引入也可以使用
import { defineProps, withDefaults } from 'vue';
import {type Persons} from '@/types'

// 接收a 同时保存起来 可以在脚本中使用
// const x = defineProps(['a', 'b']);
// console.log(x.a);

// 接收list 但这样无法在脚本中使用
// defineProps(['list']);

// 接收list 并限制类型
// defineProps<{list:Persons}>();

// 接收list 并限制类型 并限制必要性 并指定默认值
withDefaults(defineProps<{list?:Persons}>(), {
    list: () => [
        {
            name: '张三',
            age: 18,
            id: '1',
        },
        {
            name: '李四',
            age: 20,
            id: '2',
        }
    ]
});
</script>

http://www.kler.cn/a/393731.html

相关文章:

  • vscode远程连接服务器并启用tmux挂载进程
  • Linux如何更优质调节系统性能
  • 94个属于一区且接受医工交叉领域投稿的期刊汇总|个人观点·24-11-13
  • win32 / WTL 开发多线程应用,子线程传递大对象给UI线程(主窗口)的方法
  • 《深度解析 C++中的弱引用(weak reference):打破循环依赖的利器》
  • 大数据技术之HBase中的HRegion
  • Linux 网络编程
  • 开源模型应用落地-qwen模型小试-Qwen2.5-7B-Instruct-tool usage入门-集成心知天气(二)
  • Linux源码阅读笔记-V4L2框架基础介绍
  • 基于微信小程序的计算机实验室排课与查询系统
  • ubuntu22.04与ubuntu24.10使用Remmina远程桌面共享
  • android开发
  • 主动测量View的宽高
  • 隧道技术-tcp封装icmp出网
  • 【前端】技术演进发展简史
  • 统计HBase表记录条数的方法
  • shellLoad
  • 机器学习(1)线性回归
  • 2024年11月12日Github流行趋势
  • ubuntu cmake CPack将第三方库进行打包
  • 机器学习—决定下一步做什么
  • 关于学习炸鸡佬智能手表 应用硬件IIC1来取代原来软件模拟的IIC
  • Java编程优化:深入理解多态和接口中的方法实现
  • 支持向量机 SVM
  • 密码学在网络安全中的应用
  • 基于ABNF语义定义的HTTP消息格式