toRef与toRefs

使用它,消费者组件可以解构/展开返回的对象而不会失去响应性:

import { reactive,toRefs,toRef } from 'vue'
const person = reactive({
  name: '张三',
  age: 18
})

const cityObj = reactive({
  name: '北京',
  id: 'asdasxzc'
})

// 消费者组件可以解构/展开返回的对象而不会失去响应性
let { name, age } = toRefs(person)

let city = toRef(cityObj,'name')

computed()函数

创建一个只读的计算属性 ref:

const count = ref(1)
const plusOne = computed(() => count.value + 1)

console.log(plusOne.value) // 2

plusOne.value++ // 错误

创建一个可写的计算属性 ref:

const count = ref(1)
const plusOne = computed({
  get: () => count.value + 1,
  set: (val) => {
    count.value = val - 1
  }
})

plusOne.value = 1
console.log(count.value) // 0

watch()函数

用于声明在数据更改时调用的侦听回调。

  • **immediate**:在侦听器创建时立即触发回调。第一次调用时,旧值将为 undefined

  • **deep**:如果源是对象或数组,则强制深度遍历源,以便在深度变更时触发回调。详见深层侦听器

  • **flush**:调整回调的刷新时机。详见回调的触发时机watchEffect()

  • **onTrack / onTrigger**:调试侦听器的依赖关系。详见侦听器调试

    监听ref数据时:

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


// 默认是不会开启深度监听的,如果需要开启深度监听,需要在watch中传入deep参数
// deep: true
watch(person, (newVal, oldVal) => {
  console.log(newVal, oldVal)
}, {
  deep: true
})
 监听reactive数据时:
let person = reactive({
  name: "张三",
  age: 18
})

// 默认开启深度监听,并且无法修改
watch(person, (newValue, oldValue) => {
  console.log(newValue, oldValue)
})

​ 监听响应式对象中的单个属性

const person = reactive({
  name: '张三',
  age: 18,
  adress: {
    city: '北京',
    street: '北京路'
  }
})


// 如果要监听某个属性,可以使用getter函数
// 1.如果这个属性值是基本类型,只能写成getter函数
watch(()=>person.name, (newVal, oldVal) => {
  console.log(newVal, oldVal)
})


/* 
    2.如果这个属性值是对象,如果写成getter函数,
    那么就是监听的地址的变换,里面单个属性变化监听不到,但是可以开启deep,进行深度监听
    如果不写成函数,那么就是监听里面单个属性的变化,无法监听地址的变换
*/
watch(()=>person.adress, (newVal, oldVal) => {
  console.log(newVal, oldVal)
})

监听响应式对象中的单个属性:

// 如果要监听多个属性,写成数组即可
watch([()=>person.name, ()=>person.adress], (newVal, oldVal) => {
  console.log(newVal, oldVal)
})

watchEffect()函数

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

与watch的区别:watch需要指定数据源进行监听

let height = ref(0)
let weight = ref(0)

watchEffect(() => {
  if(height.value > 5 && weight.value > 10){
    console.log("发送服务器消息")
  }
})

ref与dom结构的联动

使用选项式 API,引用将被注册在组件的 this.$refs 对象里:

<!-- 存储为 this.$refs.p -->
<p ref="p">hello</p>

使用组合式 API,引用将存储在与名字匹配的 ref 里:

<script setup>
import { ref } from 'vue'

const p = ref()
</script>

<template>
  <p ref="p">hello</p>
</template>

用于组件时:

// test组件
<template>
   <h2>我是一个组件</h2>
</template>

<script setup>
import { ref } from 'vue'
let a = ref(0)
let b = ref(1)
let c = ref(2)

defineExpose({a,b,c})
</script>

<style lang="scss" scoped>

</style>
<template>
  <button @click="getDom">获取dom</button>
  <test ref="tes"></test>
</template>

import test from './components/test.vue'

let tes = ref();

// 如果想要获取组件里面的变量,需要组件自行导出
function getDom() {
  console.log(tes.value.a);
  console.log(tes.value.b);
  console.log(tes.value.c);
}

defineProps()

// 类型限制+默认值+是否必传
let props = withDefaults(defineProps<{list?:PersonList}>(),{
   // 默认值
   list:()=>[{id:'asdasdzxc',name:'海尔',age:22}]
})

基本路由

import { createRouter, createWebHistory } from 'vue-router';


import Home from '@/views/Home.vue';
import News from '@/views/News.vue';
import About from '@/views/About.vue';
import NewsDetails from '@/views/NewsDetails.vue';

const router = createRouter({
    history: createWebHistory(),
    routes: [
        {
            path: '/home',
            component: Home,
        },
        {
            path: '/news',
            component: News,
            children: [
                {
                    path: 'details',
                    component: NewsDetails,
                },
            ],
        },
        {
            path: '/about',
            component: About,
        },

        // 重定向
        {
            path: '/:pathMatch(.*)*',
            redirect: to => {
                return { path: '/home' };
            },
        },
    ]
})


export default router;

query传参

当我点击某个按钮,让它跳转到新闻详情页面时:/news/details?id=${item.id}&title=${item.title}

如何接收传的值呢?

<template>
  <div>
    新闻详情
    <ul>
      <li>{{ route.query.id }}</li>
      <li>{{ route.query.title }}</li>
    </ul>
  </div>
</template>
<script lang="ts" setup>
import {useRoute} from "vue-router";
const route = useRoute();
</script>

params传参

也就是需要这样传参:/news/details/${item.id}/${item.title}

此时要怎样接收参数呢?

改变路由结构:

{
    path: '/news',
        component: News,
            children: [
                {
                    path: 'details/:id/:title',
                    component: NewsDetails,
                },
            ],
},

接收:

<template>
  <div>
    新闻详情
    <ul>
      <li>{{ route.params.id }}</li>
      <li>{{ route.params.title }}</li>
    </ul>
  </div>
</template>
<script lang="ts" setup>
import {useRoute} from "vue-router";
const route = useRoute();

路由props配置

之前所说的query传参和params传参,在接收时感觉比较繁琐,接下来看看路由props配置,告别繁琐

首先改变路由:

{
    path: '/news',
        component: News,
            children: [
                {
                    path: 'details',
                    component: NewsDetails,

                    // 第一种params写法
                    // props: true,

                    // 第二种query写法
                    props(route){
                        return route.query;
                    },
                },
            ],
},

接收:

<template>
  <div>
    新闻详情
    <ul>
      <li>{{ id }}</li>
      <li>{{ title }}</li>
    </ul>
  </div>
</template>
<script lang="ts" setup>
defineProps(['id', 'title'])
</script>