Vue3学习(二)-----数据

136 阅读4分钟

ref

ref接受一个内部值并返回一个响应式可变的ref对象

在模版中使用一个ref,当ref的值发生改变时,Vue会自动检测值的变化,并根据值更新DOM。
Ref 可以持有任何类型的值,包括深层嵌套的对象、数组或者 JavaScript 内置的数据结构,比如 Map

const count = ref(0)
const Person = ref({name:'张三'})

const arr = ref(['1','2','3'])

ref 也可以获取DOM,需要在DOM渲染之后获取

<script setup lang="ts">

import { isRef, ref } from 'vue';

const count = ref(0)

count.value = 5

console.log(isRef(count))

console.log(count.value)

const Person = ref({name:'张三'})

const arr = ref(['1','2','3'])

const htmlref = ref<HTMLInputElement>()

const outputInfo = ()=>{

console.log(htmlref.value)

}

</script>

<template>

<button @click="count++">{{ count }}</button>

<p>{{ Person.name }}</p>

<ul>

<li v-for="name in arr" :value="name" :key="name">{{ name }}</li>

</ul>

<input ref="htmlref" placeholder="输入数字">

<button @click="outputInfo">输出html</button>

</template>

reactive

reactive 定义一个对象类型的响应式数据,返回一个proxy实例对象,不能使用基础数据类型

refreactive都是将我们的变量变成响应式
ref 支持所有的类型,reactive引用类型 Array Object Map Set ref 取值 赋值 都需要加.value,reactive是不需要.value

<script setup lang="ts">

import { reactive } from 'vue';

type P = {

name:string,

age:number

}

const Person = reactive<P>({name:'张三',age: 18})

let list = reactive<string[]>([])

const addItem = ()=>{

// list.push('Hello')

let arr = ['hello','vue3','!']

//如果直接赋值 页面不会发生变化

// list = arr

//可以解构 给list赋值

list.push(...arr)

}

</script>

<template>

<div>

姓名: {{ Person.name }}<br>

年龄: {{ Person.age }}

</div>

<div>

<ul v-for="item in list" :key="item">

<li>{{ item }}</li>

</ul>

</div>

<button @click="addItem">添加</button>

</template>

toRef toRefs toRow

toRef

toRef 的作用是将一个响应式对象中的属性转换成单独的响应式引用

toRefs

toRefs 将一个对象的所有属性变成响应式引用,追踪原对象的引用关系

toRaw

toRaw 将一个响应式对象变成非响应式

<script setup lang="ts">

import { reactive, toRaw, toRef, toRefs } from 'vue';

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

let like = toRef(person,'like')

let {name, age} = toRefs(person)

const changeName = ()=>{

like.value = '睡觉'

console.log(person)

}

const changePerson = ()=>{

name.value = '李四'

age.value = 15

}

const toRawPerson = ()=>{

console.log(toRaw(person))

}

</script>

<template>

<div>

{{ person }}

</div>

<button @click="changeName">改变</button>

<button @click="changePerson">改变2</button>

<button @click="toRawPerson">改变3</button>

</template>

计算属性(computed)

computed 基于组件的响应式依赖进行复杂的计算,并返回一个新的响应式引用

<script setup lang="ts">

import { computed, ref } from 'vue';

let count = ref(1)

let count2 = computed(()=>count.value*2)

const changeCount = ()=>{

count.value = 2

}

</script>

<template>

<div>

原始数据{{ count }}<br>

计算后数据 {{ count2 }}<br>

</div>

<button @click="changeCount">改变数据</button>

</template>

应用场景
1.格式化数据

<script setup lang="ts">

import { computed, ref } from 'vue';

let date = ref(20240519)

let dateStr = computed(()=>{

let str = date.value.toString()

return str.substring(0,4)+`-`+str.substring(4,6)+`-`+str.substring(6,8)

})

</script>

<template>

<div>
<!-- 格式化数据---2024-05-19 -->
格式化数据---{{ dateStr }}<br>

</div>

</template>

2.对多个数据计算

<script setup lang="ts">

import { computed, ref } from 'vue';

let num = ref(5)

let price = ref(20)

let totalPrice = computed(()=>{

return num.value*price.value

})

</script>

<template>

<div>

<!-- 总价格---100 -->

总价格---{{ totalPrice }}<br>

</div>

</template>

3.减少模版中的逻辑计算,过滤,排序等操作

<script setup lang="ts">

import { computed, reactive } from 'vue'

type student = {

name:string,

age:number,

score:number,

}

let data = reactive<student[]>([

{name: '张三', age:18, score: 80},

{name: '李四', age:19, score: 60},

{name: '王五', age:20, score: 100 },

{name: '小李', age:18, score: 100 },

{name: '小小', age:16, score: 85}

]);

let dataLength = computed(()=>{

return data.length

})

let bestScore = computed(()=>{

let score = 0

let arr = []

for (const element of data) {

if(element.score>score){

score = element.score

}

}

for (const element of data) {

if(element.score==score){

arr.push(element)

}

}

return arr

})

let printArr = (array:student[])=>{

array.forEach(element => {

console.log('姓名:'+element.name+' 年龄:'+element.age+' 得分:'+element.score+'\n')

});

}

console.log('同学个数:'+dataLength.value);

printArr(bestScore.value)

</script>

<template>

<div>

</div>

</template>

列表渲染

列表渲染主要通过v-for循环数据渲染列表
遍历数组:v-for="(item, index) in items"
遍历对象:v-for="(value, key, index) in object"

绑定数据渲染列表

<script setup lang="ts">

import { ref } from 'vue'

let list = ref([

{text: 'A'},

{text: 'B'},

{text: 'C'}

])

</script>

<template>

<div>

<ul>

<li v-for="item in list">{{ item.text }}</li>

</ul>

</div>

</template>

v-for 还支持一个可选的第二个参数,参数值为当前项的索引:

<div>

<ul>

<li v-for="(item, index) in list">{{ index }}-----{{ item.text }}</li>

</ul>

</div>

v-for遍历对象

let object = reactive({

name:'张三',

age:20,

gendar:'man',

hobby:'睡觉'

})

<li v-for="value in object">{{ value }}</li>

支持第二个可选参数key

<li v-for="(value, key) in object">{{ key }}----{{ value }}</li>

第三个参数index

<li v-for="(value, key, index) in object">{{ index }}-{{ key }}--{{ value }}</li>

key管理状态
使用 v-for 渲染列表时,为每个项提供一个唯一的 key 属性,以便 Vue 能够识别每个项的唯一性,从而进行高效的 DOM 更新。 key应为字符串或数字,不能用对象最为key

<div v-for="item in items" :key="item.id">
  <!-- 内容 -->
</div>

侦测数组变化 数组有一系列方法改变数组内容。 使原数组发生改变的方法有:push() pop() shift() unshift() splice() sort() reverse()
不改变原数组生成新数组的有:filter() concat() slice()

const arr = reactive([1,2,3,4,5,6,7])

const evenArr = computed(()=>{

return arr.filter((n)=>n%2===0)

})
<li v-for="(item,index) in evenArr" :key="index">{{ item }}</li>

watch侦听器

watch 的作用是用于监测响应式属性的变化,并在属性发生改变时执行特定的操作
watch 的第一个参数可以是不同形式的“数据源”:它可以是一个 ref (包括计算属性)一个响应式对象一个 getter 函数多个数据源组成的数组
第二个参数回调函数callback(newVal, oldVal)
第三个参数一个options配置项是一个对象{immediate:true,//是否立即调用一次 deep:true //是否开启深度监听once: true //监听一次}

<script setup lang="ts">

import { ref, watch } from 'vue'

let x = ref(0)

let y = ref(3)

watch(x,(newx)=>{

console.log(`x 的值 ${newx}`)

})

watch([x,y],([newx,newy])=>{

console.log(`x的值${newx}, y的值${newy}`)

})

watch(()=>x.value+y.value,(sum)=>{

console.log(`x+y的值为${sum}`)

})

const changeX = ()=>{

x.value++

}

const changeY = ()=>{

y.value++

}

</script>

<template>

<div>

<button @click="changeX">改变X</button>

<button @click="changeY">改变Y</button>

</div>

</template>

## watchEffect()
watchEffect 是 Vue 3 中提供的一个函数,用于创建即时执行的侦听器。它会立即执行一次传入的函数,同时会追踪函数内部使用到的响应式数据,当这些数据发生变化时,会再次执行该函数。

const num1 = ref(0)

watchEffect(()=>{

console.log(`num1的值发生了改变${num1.value}`)

})

num1.value = 5

打印
num1的值发生了改变0
num1的值发生了改变5

watch vs. watchEffect

watchwatchEffect 都能响应式地执行有副作用的回调。它们之间的主要区别是追踪响应式依赖的方式:

  • watch 只追踪明确侦听的数据源。它不会追踪任何在回调中访问到的东西。另外,仅在数据源确实改变时才会触发回调。watch 会避免在发生副作用时追踪依赖,因此,我们能更加精确地控制回调函数的触发时机。
  • watchEffect,则会在副作用发生期间追踪依赖。它会在同步执行过程中,自动追踪所有能访问到的响应式属性。这更方便,而且代码往往更简洁,但有时其响应性依赖关系会不那么明确。

存储

Pinia 是 Vue 3 官方推荐的状态管理库,用于管理应用的全局状态。 安装

npm i pinia 
npm i pinia-use-persist

main.ts中引入使用

import { createApp } from 'vue'
import './style.css'
import App from './App.vue'
import { createPinia } from 'pinia'
import { usePersist } from 'pinia-use-persist'
const pinia = createPinia()
pinia.use(usePersist)
createApp(App).use(pinia).mount('#app')

创建src/store/文件夹下的index.ts

import { defineStore } from "pinia";

  


export const useLoginStore = defineStore('Login',{

state: ()=>({

logined: false,

name: '张三'

}),

persist: {

enable: true,

encryptionKey: 'letscode',

storage: localStorage,

}

})

在组件中使用

<script setup lang="ts">

import { useLoginStore } from '../store';

const loginstate = useLoginStore();

const add = ()=>{

loginstate.$state.name = '李四'

}

</script>

<template>

<div>

<p>{{ loginstate.name }}</p>

<button @click="add">改变</button>

</div>

</template>