记录学习尚硅谷视频的笔记
禹神YYDS
网站地址:vue视频
核心语法
setup
setup 是组合型数据
setup() {
// 数据
// let 不是响应式的
let name = '张三';
let age = 25;
let tel = '13812345678';
// 方法
function changeName() {
name = 'zhangsan';
}
function changeAge() {
age+=1;
}
function showTel() {
alert(tel);
}
return {
name,
age,
changeName,
changeAge,
showTel
}
}
setup 与 data 之间的关系
setup语法糖
<script setup lang="ts" name="PersonGH"> // name 定义插件的名字
// 数据
// let 不是响应式的
let name = '张三';
let age = 25;
let tel = '13812345678';
// 方法
function changeName() {
name = 'zhangsan';
}
function changeAge() {
age += 1;
}
function showTel() {
alert(tel);
}
</script>
合并script,需要插件 vite-plugin-vue-setup-extend
命令行:npm i vite-plugin-vue-setup-extend -D
响应式数据
ref
ref 创建基本类型的响应式数据 和对象事件的响应数据
ref 类型是一个对象,script需要通过 .value获取数据
<script setup lang="ts" name="PersonGH">
import { ref } from 'vue'; // ref 响应式API
// 数据
let name = ref('张三');
let age = ref(25);
let addr = '南通市崇川区啬园路9号'; // let 不是响应式的
let tel = '13812345678';
// 方法
function changeName() {
name.value = 'zhangsan';
}
function changeAge() {
age.value += 1;
}
function showTel() {
alert(tel);
}
</script>
标签的ref属性
父模板与子模版具有id属性,获取id元素获取到父模板元素
父模板
<template>
<h5 id="t1">Hello World</h5>
<ref_shuxin/>
</template>
<script lang="ts" setup name="APP">
import ref_shuxin from './components/ref_shuxin.vue';
</script>
子模版
<template>
<div class="ref_shuxin">
<h1 id="t1">Python</h1>
<h1>C++</h1>
</div>
</template>
<script lang="ts" setup name="RefShuxin">
function handleClick() {
console.log(document.getElementById('t1'))
}
</script>
输出结果:
ref属性可以避免这个问题
父模板
<template>
<h5 ref="t1">Hello World</h5>
<ref_shuxin />
</template>
<script lang="ts" setup name="APP">
import ref_shuxin from './components/ref_shuxin.vue';
</script>
子模版
<template>
<div class="ref_shuxin">
<h1 id="t1">Python</h1>
<h1 ref="t2">Java</h1>
<h1>C++</h1>
<button @click="handleClick"> 输出</button>
</div>
</template>
<script lang="ts" setup name="RefShuxin">
import { ref } from 'vue'
// 存储ref标记的元素
let t2 = ref(null)
function handleClick() {
console.log(t2.value)
}
</script>
ref 可以作用于子模板
父模板
<template>
<h5 id="t1">Hello World</h5>
<h2 ref="t2">哈哈哈~~~意不意外</h2>
<ref_shuxin ref="r"/>
<button @click="change">组件切换</button>
</template>
<script lang="ts" setup name="APP">
import ref_shuxin from './components/ref_shuxin.vue';
import { ref } from 'vue';
let r =ref();
function change() {
console.log(r.value);
}
</script>
子模版
注意: 子模版中添加了多个ref对象
<template>
<div class="ref_shuxin">
<h1 id="t1">Python</h1>
<h1 ref="t2">Java</h1>
<h1>C++</h1>
<button @click="handleClick"> 输出</button>
</div>
</template>
<script lang="ts" setup name="RefShuxin">
import { ref } from 'vue'
// 存储ref标记的元素
let t2 = ref(null)
let a =ref(2)
let b = ref(3)
function handleClick() {
// console.log(t2.value)
console.log(document.getElementById('t1'))
}
</script>
父模板输出ref ,获取子模版的实例,但是子模版里的ref响应数据对象没有
解决方法: 引入defineExpose 对象
子模版
<template>
<div class="ref_shuxin">
<h1 id="t1">Python</h1>
<!-- <h1 id="t2">JavaScript</h1> -->
<h1 ref="t2">Java</h1>
<h1>C++</h1>
<button @click="handleClick"> 输出</button>
</div>
</template>
<script lang="ts" setup name="RefShuxin">
import { ref,defineExpose } from 'vue'
// 存储ref标记的元素
let t2 = ref(null)
// 保护对象,实例对象无法查看
let a =ref(2)
let b = ref(3)
function handleClick() {
// console.log(t2.value)
console.log(document.getElementById('t1'))
}
defineExpose({a,b}) //公开对象
</script>
defineExpose公开 a,b 父模板可以获取到a,b
子模版中响应数据是保护的,没有公开给父模板的数据,父模板无法使用
reactive
reactive 创建对象事件的响应数据
<script lang="ts" setup>
import { ref } from 'vue'
import {reactive} from 'vue'
// 数据
let car = reactive({brand: '宝马', price: 100000})
// 方法
function changePrice() {
car.price += 10000
}
</script>
ref 和 reactive之间的关系
-
ref 创建的对象事件的响应函数 是基于 reactive 的封装,ref.value === reactive
-
reactive 重新分配一个新对象,会失去响应式
<script lang="ts" setup> import { ref } from 'vue' import {reactive} from 'vue' // 数据 let car = reactive({brand: '宝马', price: 100000}) let car2 = ref({brand: '奔驰', price: 200000}) // 方法 function changePrice() { car.price += 10000 } function changeCar() { // car = {brand: '比亚迪', price: 100000} 失去响应性,无法更新视图 // car = reactive({brand: '比亚迪', price: 100000}) 失去响应性,无法更新视图 // car.brand = '比亚迪' // car.price = 100000 Object.assign(car, {brand: '比亚迪', price: 100000}) } function changeCar2() { car2.value = {brand: '比亚迪', price: 100000} } </script>
Object.assign(x,y) 将 对象y 分配给 对象x
-
使用原则
1.基本类型的响应式数据,必须用 ref 2.响应式对象,如果层级不深,ref 和 reactive 都可以;如果层级深,推荐使用reactive
torefs 和 toref
torefs 将 reactive 的键值对 转换成 ref 对象
<script lang="ts" setup name="Person_new">
import { reactive, toRef, toRefs } from 'vue';
let person =reactive({
name: '张三',
age: 25,
})
// let { name, age } = person; // name 和 age 都不是响应式的,不可以直接使用
//
let { name, age } = toRefs(person); // name 和 age 是响应式的,可以直接使用
console.log(toRefs(person));
let myname = toRef(person, 'name'); // myname 是响应式的,可以直接使用
console.log(myname.value);
function changeName() {
person.name += '_'
}
function changeAge() {
person.age += 1;
}
</script>
let { name, age } = person; // name 和 age 都不是响应式的
let { name, age } = toRefs(person); // name 和 age 是响应式的,可以直接使用
// name 和 age 数据的改变,person 数据也改变
toref 将 reactive 一项数据 转换成 ref 对象
计算属性
- 计算属性有缓存,重复获取相同数据,只计算一次
- 计算属性默认只读,需要写操作需要定义
- 计算属性获取的数据是ref类型数据
<script setup lang="ts">
import { ref, computed} from 'vue'
let One = ref('G')
let Two = ref('H')
// 计算属性 ,只读属性
let name = computed(()=>{
//从现有数组中提取一个子数组。它接受两个参数,起始和结束位置(可选),
//并返回一个新的数组,包含从起始位置到结束位置的元素
return One.value.slice(0,1).toUpperCase()+One.value.slice(1) +'-'+ Two.value
})
// 计算属性 ,读写属性
let name = computed({
get(){
return One.value.slice(0,1).toUpperCase()+One.value.slice(1) +'-'+ Two.value
},
set(val){
const[fisrtName, lastName] = val.split('-')
One.value = fisrtName
Two.value = lastName
}
})
function changeName() {
name.value = '顾-皓';
}
</script>
监视
watch
-
作用: 监视数据的变化
-
特点: Vue3 中的 watch 只能监视四种数据:
1. ref 定义的数据 2. reactive 定义的数据 3. 函数返回一个值 4. 一个包含上述内容的数组
1.监视 【ref】 定义的【基本数据类型】
<script setup lang="ts" name="watch">
import {ref,watch} from 'vue';
let sum = ref(0);
function sumWatch() {
sum.value++;
}
watch(sum,(newValue,oldValue)=>{
console.log('sum changed to',sum.value)
console.log('old value is',oldValue)
console.log('new value is',newValue)
})
// 解除监视
const stopwatch = watch(sum,(newValue,oldValue)=>{
console.log('old value is',oldValue)
console.log('new value is',newValue)
if(newValue === 10) stopwatch();
})
</script>
2.情况二: 监视 【ref】 定义的【对象类型】
若修改的是ref定义的对象的属性,newVal 和 oldVal 都是新值
若修改整个ref定义的对象,newVal 是新值,oldVal是旧值,不是同一个对象
<script setup lang="ts" name="watch">
import {ref,watch} from 'vue';
let person = ref({name:'张三',age:20});
function changeName() {
person.value.name += '-'
}
function changeAge() {
person.value.age++;
}
function changePerson() {
person.value = {name:'李四',age:25}
}
// watch 三个参数 被监视的数据 监视的回调 配置的对象
watch(person,(newValue,oldValue)=>{
// 监测的是对象的地址值
console.log('person changed to',newValue,oldValue)
// 检测对象内部属性的变化,需要手动开启深度监测(deep)
// 对象内部的属性值变化,也会触发watch回调函数
// immediate 选项,初次渲染也会触发watch回调函数
},{deep:true,immediate:true})
</script>
3.监视 【reactive】 定义的【对象类型】数据 ,默认开启深度监测 【不可以关闭】
<script setup lang="ts" name="watch">
import { ref, watch, reactive } from 'vue';
let person = reactive({ name: '张三', age: 20 });
function changeName() {
person.name += '-'
}
function changeAge() {
person.age++;
}
function changePerson() {
Object.assign(person, { name: '李四', age: 25 })
}
watch(person, (newValue, oldValue) => {
console.log('person from', newValue, 'change to', oldValue)
})
</script>
4.监视 reactive 或 ref 定义的【对象类型】数据的某个属性
1. 属性值不是【对象类型】,需要写成函数形式
2. 属性值是【对象类型】,可以直接编写,也可以用函数形式(推荐)
<script setup lang="ts" name="watch1">
import { ref, watch, reactive } from 'vue';
let person = reactive({
name: '张三',
age: 20 ,
car:{
c1:'宝马',
c2:'奔驰'
}
});
function changeName() {
person.name += '-'
}
function changeAge() {
person.age++;
}
function changeC1() {
person.car.c1 = '奥迪'
}
function changeC2() {
person.car.c2 = '大众'
}
function changeCar() {
person.car = {c1:'问界',c2:'比亚迪'}
}
watch(()=>{return person.name},()=>{
console.log('name changed to',person.name)
})
watch(person.car,(newValue,oldValue)=>{
console.log('car changed to',newValue,oldValue)
})
watch(()=>person.car,(newValue,oldValue)=>{
console.log('car changed to',newValue,oldValue)
},{deep:true})
</script>
5.监视上述多种情况的变化
<script setup lang="ts" name="watch1">
import { ref, watch, reactive } from 'vue';
let person = reactive({
name: '张三',