【涅槃】Vue3学习笔记(二)

103 阅读6分钟

computed的使用
定义

computed是一个函数,用于创建计算属性(computed properties)。 计算属性是基于其他响应式数据派生出来的值,当依赖的响应式数据发生变化时,计算属性会自动重新计算。

特点

  1. 缓存机制:计算属性是惰性的,只有当依赖的响应式数据发生变化时,才会重新计算。
  2. 只读或可写:可以创建只读的计算属性,也可以创建可写的计算属性。
  3. 依赖响应式数据:计算属性依赖于refreactive或其他计算属性。

语法

import { computed } from 'vue';

// 只读计算属性
const computedValue = computed(() => {
  // 计算逻辑
  return someReactiveData.value + 10;
});

// 可写计算属性
const computedValue = computed({
  get() {
    return someReactiveData.value;
  },
  set(newValue) {
    someReactiveData.value = newValue;
  }
});

示例

<template>
  <div>
    <p>Full Name: {{ fullName }}</p>
    <input v-model="firstName" placeholder="First Name" />
    <input v-model="lastName" placeholder="Last Name" />
  </div>
</template>

<script>
import { ref, computed } from 'vue';

export default {
  setup() {
    const firstName = ref('John');
    const lastName = ref('Doe');

    // 只读计算属性
    const fullName = computed(() => {
      return `${firstName.value} ${lastName.value}`;
    });

    return {
      firstName,
      lastName,
      fullName
    };
  }
};
</script>

使用场景

  • 当你需要基于响应式数据派生出新的值时(如格式化数据、计算总和等)。
  • 当你需要优化性能,避免不必要的计算时(利用缓存机制)。

watch的使用

定义

watch是一个函数,用于监听响应式数据的变化,并执行副作用(side effects)。它允许你对响应式数据的变化做出响应,例如发送网络请求、更新 DOM 或调用外部函数。

特点

  1. 监听响应式数据:可以监听refreactive对象或计算属性。
  2. 立即执行:可以通过immediate: true选项在初始化时立即执行回调函数。
  3. 深度监听:可以通过deep: true选项监听对象内部属性的变化。
  4. 清理副作用:可以在回调函数中返回一个清理函数,用于清理上一次执行的副作用。

语法

import { watch } from 'vue';

// 监听单个响应式数据
watch(someReactiveData, (newValue, oldValue) => {
  console.log(`New value: ${newValue}, Old value: ${oldValue}`);
});

// 监听多个响应式数据
watch([ref1, ref2], ([newValue1, newValue2], [oldValue1, oldValue2]) => {
  console.log(`New value 1: ${newValue1}, Old value 1: ${oldValue1}`);
  console.log(`New value 2: ${newValue2}, Old value 2: ${oldValue2}`);
});

示例

<template>
  <div>
    <p>Count: {{ count }}</p>
    <button @click="increment">Increment</button>
  </div>
</template>

<script>
import { ref, watch } from 'vue';

export default {
  setup() {
    const count = ref(0);

    function increment() {
      count.value++;
    }

    // 监听 count 的变化
    watch(count, (newValue, oldValue) => {
      console.log(`Count changed from ${oldValue} to ${newValue}`);
    });

    return {
      count,
      increment
    };
  }
};
</script>

使用场景

  • 当你需要对响应式数据的变化做出响应时(如发送网络请求、更新 DOM 等)。
  • 当你需要监听多个响应式数据的变化时。
  • 当你需要在初始化时立即执行某些逻辑时(通过immediate: true)。

watchEffect的补充说明

除了watch,Vue 3 还提供了一个更高级的函数watchEffect,用于自动收集依赖并响应变化。它类似于watch,但不需要显式指定依赖,而是自动收集回调函数中使用的响应式数据。

语法

import { watchEffect } from 'vue';

watchEffect(() => {
  console.log(`Count is now ${count.value}`);
});

特点

  • 自动收集依赖,无需显式指定。
  • 默认立即执行回调函数。
  • 可以返回清理函数。

示例

<template>
  <div>
    <p>Count: {{ count }}</p>
    <button @click="increment">Increment</button>
  </div>
</template>

<script>
import { ref, watchEffect } from 'vue';

export default {
  setup() {
    const count = ref(0);

    function increment() {
      count.value++;
    }

    // 使用 watchEffect 自动收集依赖
    watchEffect(() => {
      console.log(`Count changed to ${count.value}`);
    });

    return {
      count,
      increment
    };
  }
};
</script>

使用场景

  • 当你需要自动收集依赖,而无需显式指定时。
  • 当你需要更简洁的代码时。

总结

computed

  • 用于创建基于响应式数据派生的值。
  • 是惰性的,只有在依赖变化时才会重新计算。
  • 适用于需要缓存的派生值。

watch

  • 用于监听响应式数据的变化,并执行副作用。
  • 可以监听单个或多个响应式数据。• 提供更多控制选项(如immediatedeep)。 watchEffect
  • 自动收集依赖,无需显式指定。
  • 默认立即执行回调函数。
  • 更适合需要自动响应依赖变化的场景。

标签中的ref使用

定义

ref在 Vue 3 中有两种用途:

  1. 模板中的ref:用于给 DOM 元素或子组件实例添加引用,方便在 JavaScript 中访问它们。
  2. Composition API 中的ref:用于创建响应式数据(与模板无关)。

模板中的ref使用在模板中,ref是一个特殊的属性,用于给 DOM 元素或子组件实例添加引用。它可以在setup()函数中通过ref函数访问。

语法

<template>
  <input ref="inputRef" />
  <ChildComponent ref="childRef" />
</template>

setup()中访问:

import { ref, onMounted } from 'vue';

export default {
  setup() {
    const inputRef = ref(null); // 创建一个 ref 来存储 DOM 引用
    const childRef = ref(null); // 创建一个 ref 来存储子组件实例

    onMounted(() => {
      console.log(inputRef.value); // 访问 DOM 元素
      console.log(childRef.value); // 访用子组件实例
    });

    return {
      inputRef,
      childRef
    };
  }
};

特点

  1. 访问 DOM 元素:通过ref可以直接访问 DOM 元素,例如获取输入框的值或操作 DOM。
  2. 访问子组件实例:可以访问子组件的实例,从而调用子组件的方法或访问子组件的props
  3. 默认值为null:在组件挂载之前,ref的值为null

示例

<template>
  <input ref="inputRef" placeholder="Enter something" />
  <button @click="focusInput">Focus Input</button>
</template>

<script>
import { ref, onMounted } from 'vue';

export default {
  setup() {
    const inputRef = ref(null);

    // 定义一个方法,聚焦到输入框
    function focusInput() {
      inputRef.value.focus(); // 访问 DOM 元素并调用 focus 方法
    }

    return {
      inputRef,
      focusInput
    };
  }
};
</script>

props的使用

定义

props是子组件接收父组件传递的数据的方式。它允许父子组件之间进行数据通信。

使用方法

  1. 定义props:在子组件中定义props,声明需要接收的数据。
  2. 传递props:在父组件中通过子组件的属性传递数据。

语法

子组件中定义props

<script>
export default {
  props: {
    title: String, // 接收一个字符串类型的 prop
    count: Number // 接收一个数字类型的 prop
  }
};
</script>

父组件中传递props

<template>
  <ChildComponent :title="headerTitle" :count="itemCount" />
</template>

<script>
import ChildComponent from './ChildComponent.vue';

export default {
  components: {
    ChildComponent
  },
  data() {
    return {
      headerTitle: 'Hello Vue 3!',
      itemCount: 10
    };
  }
};
</script>

特点

  1. 单向数据流:props是单向的,只能从父组件传递到子组件,不能反向修改。
  2. 类型检查:可以在props中定义类型,Vue 会自动进行类型检查。
  3. 默认值:可以通过default属性为props提供默认值。
  4. 动态绑定:使用v-bind(简写为:)动态绑定props

示例

子组件:

<template>
  <div>
    <h1>{{ title }}</h1>
    <p>Count: {{ count }}</p>
  </div>
</template>

<script>
export default {
  props: {
    title: {
      type: String,
      required: true
    },
    count: {
      type: Number,
      default: 0
    }
  }
};
</script>

父组件:

<template>
  <ChildComponent :title="headerTitle" :count="itemCount" />
</template>

<script>
import ChildComponent from './ChildComponent.vue';

export default {
  components: {
    ChildComponent
  },
  setup() {
    const headerTitle = 'Hello Vue 3!';
    const itemCount = 5;

    return {
      headerTitle,
      itemCount
    };
  }
};
</script>

refprops的区别

特性refprops
用途引用 DOM 元素或子组件实例在父子组件之间传递数据
定义方式在模板中通过 ref="name" 定义在子组件中通过 props 定义
访问方式setup() 中通过 ref 函数访问在子组件中直接使用
数据流向单向(父组件 -> 子组件)单向(子组件 -> 父组件)
默认值默认为 null可以通过 default 提供默认值
响应式是(引用的 DOM 或实例是响应式的)是(传递的数据是响应式的)

总结

ref

  • 用于引用 DOM 元素或子组件实例。
  • 在模板中通过ref="name"定义,在setup()中通过ref函数访问。
  • 常用于操作DOM或调用子组件的方法。

props

  • 用于在父子组件之间传递数据。
  • 在子组件中通过props定义,在父组件中通过属性传递。
  • 是单向数据流,只能从父组件传递到子组件。