vue3学习笔记之响应式状态

响应式状态

src/views/basic/Reactive.vue

<script setup>
import { ref, reactive, computed, watch, watchEffect } from "vue";

//reactive 响应式对象 只能用于对象、数组和集合类型
const author = reactive({
  name: "John Doe",
  books: ["Vue 2 - Advanced Guide", "Vue 3 - Basic Guide", "Vue 4 - The Mystery"],
});

//计算属性 值会基于其响应式依赖被缓存。计算属性仅会在其响应式依赖更新时才重新计算。
const publishedBooksMessage = computed(() => {
  return author.books.length > 0 ? "Yes" : "No";
});

// 声明响应式状态
const firstName = ref("John");
const lastName = ref("Doe");
const fullName = computed({
  get() {
    return firstName.value + " " + lastName.value;
  },
  set(newValue) {
    [firstName.value, lastName.value] = newValue.split(" "); // 解构赋值语法
  },
});

const fullname_text = ref(null);
const fullname_num_text = ref(null);

const num = ref(5);
// 侦听器 使用 watch 函数在每次响应式状态发生变化时触发回调函数
// 可以直接侦听一个 ref
watch(num, (newnum, oldnum) => {
  if (newnum > 30) {
    num.value = 0;
  }
});

// getter 函数
watch(
  () => firstName.value + " " + lastName.value,
  (full_name) => {
    fullname_text.value.textContent = `Full name is: ${full_name}`;
  }
);

// 多个来源组成的数组
watch([num, () => firstName.value + " " + lastName.value], ([newnum, full_name]) => {
  fullname_num_text.value.textContent = `Full name is: ${full_name},num is:${newnum}`;
});

const todoId = ref(1);
const todoData = ref(null);
// watchEffect 自动跟踪回调的响应式依赖。
watchEffect(async () => {
  const response = await fetch(`https://jsonplaceholder.typicode.com/todos/${todoId.value}`);
  todoData.value = await response.json();
});
</script>
<template>
  <div>
    <!-- 计算属性 -->
    <div>
      <p>
        Has published books:<span>{{ publishedBooksMessage }}</span>
      </p>
    </div>

    <div>
      <p>num: <input v-model.number="num" /></p>

      <p>名:<input v-model.trim="firstName" />姓:<input v-model.trim="lastName" /></p>
      <p>姓名:<input v-model.trim="fullName" /></p>
      <p ref="fullname_text">Full name is: {{ fullName }}</p>
      <p ref="fullname_num_text">Full name is: {{ fullName }} , num is: {{ num }}</p>
    </div>

    <!-- 侦听器 -->
    <div>
      <p>Todo id: {{ todoId }}</p>
      <button @click="todoId++">Fetch next todo</button>
      <p v-if="!todoData">Loading...</p>
      <pre v-else>{{ todoData }}</pre>
    </div>
  </div>
</template>
<style scoped></style>

src/components/simple/DemoComp.vue

<script setup>
import { ref, inject } from "vue";

defineOptions({
  inheritAttrs: false, //禁用 Attributes 继承
});

const props = defineProps({
  title: String,
  greetingMessage: String,
  likes: Number,
  isPublished: Boolean,
  author: Object,
  comments: Array,
});
const emits = defineEmits(["enlargeText"]);

const count = ref(0);

// 注入上层组件提供的数据
const api_url = inject("api_url");
const module_name = inject("module_name");
const { location, updateLocation } = inject("location");
let read_only_count = inject("read_only_count");

function updateCount() {
  read_only_count.value++;
  alert("read_only_count的值为:" + read_only_count.value);
}
</script>

<template>
  <div>
    <p :class="$attrs.class">
      <span>msg:{{ title }}</span>
      <span>greetingMessage:{{ greetingMessage }}</span>
      <span>likes:{{ likes }}</span>
      <span>is-published:{{ isPublished ? "是" : "否" }}</span>
      <span>author:{{ author.name + "|" + author.company }}</span>
    </p>
    <button type="button" @click="count++">count is {{ count }}</button>
    <button @click="$emit('enlargeText')">Enlarge text</button>
    <p>
      <slot><span>default slot </span></slot>
      <slot name="slot2"><span>slot2</span></slot>
      <slot name="slot3"><span>slot3</span></slot>
      <slot name="slot4">
        <span>slot4</span>
      </slot>
    </p>

    <!-- 作用域插槽,子组件传值item给父组件 -->
    <p>
      comments:
      <span v-for="(item, index) in comments" :key="index">
        <slot name="item" v-bind="item"></slot>
      </span>
    </p>

    <p>
      App.vue注入:
      <span>{{ api_url }}</span>
    </p>
    <p>
      父级组件注入(允许修改):
      <span>{{ module_name }}</span>
      <button @click="updateLocation">{{ location }}</button>
    </p>
    <p>
      父级组件注入(不允许修改):
      <span>{{ read_only_count }}</span>
      <button @click="updateCount">update count</button>
    </p>
  </div>
</template>

<style scoped>
span {
  margin-left: 1rem;
}

button,
a {
  border: 1px solid blue;
  margin-left: 1rem;
}
</style>

image

posted @ 2023-12-26 15:23  carol2014  阅读(52)  评论(0)    收藏  举报