Vue3新特性 组合式Api

setup - 组件内使用 Composition API 的入口点

setup 作为组合式 API 的入口点,也就是说,组合式 API 都必须只能在 setup 中使用

<template>
  <div>
    <h1>setup - 组件内使用 Composition API 的入口点</h1>
    <p>{{username}}</p>
  </div>
</template>

<script>
export default {
  name: "Setup",
  props: {
    username: { type: String, default: "guao" },
  },
  //setup 先与 beforeCreate。
  setup(props, ctx) {
    console.log("setup");
    console.log(props, ctx);
    //props里面使用 父组件传来的props
    console.log(props.username, ctx);
    //由于 setup 里面不能使用 this,
    //所以不能像 vue2.x 一样使用 this.$emit(‘emitFun’, val),
    //setup 里面有两个参数,第二个参数可以进行结构得到 emit,
    //也可以直接直接使用 ctx.emit 进行 emit 事件
    ctx.emit('emitFun', {emit: true})
  },
  beforeCreate() {
    console.log("beforeCreate");
  },
};
</script>

创建组件实例,然后初始化 props ,紧接着就调用setup 函数。从生命周期钩子的视角来看,它会在 beforeCreate 钩子之前被调用。

reactive, ref - 数据响应式

reactive - 对象数据响应式
接收一个普通对象然后返回该普通对象的响应式代理。

<template>
  <div>
    <p>{{data.msg}}</p>
    <button @click="updateData">更新数据</button>
  </div>
</template>

<script>
import { reactive } from "vue";

export default {
  name: "ReactiveObject",
  setup() {
    const data = reactive({ msg: "hello world" });
    const updateData = () => {
      data.msg= "hello world " + new Date().getTime();
    };
    return { data, updateData };
  },
};
</script>

ref - 单值数据响应式
接受一个参数值并返回一个响应式且可改变的 ref 对象。

<template>
  <div>
    <h1>单值数据响应式</h1>
    <p>{{msg}}</p>
    <button @click="updateMessage">更新数据</button>
  </div>
</template>

<script>
import { ref } from "vue";

export default {
  name: "ReactiveSingleValue",
  setup() {
    const msg= ref("hello world");
    const updateMessage = () => {
      msg.value = "hello world " + new Date().getTime();
    };
    return { msg, updateMessage };
  },
};
</script>

computed - 计算属性

只传 getter
返回一个默认不可手动修改的 ref 对象。

<template>
  <div>
    <h1>computed - 计算属性</h1>
    <p>{{username}}</p>
  </div>
</template>

<script>
import { reactive, computed } from "vue";
export default {
  name: "Computed",
  setup() {
    const user = reactive({ firstname: "chen", lastname: "haihong" });
    const username = computed(() => user.firstname + " " + user.lastname);
    username.value = "hello world"; // 报警告,computed value is readonly
    return { username };
  },
};
</script>

同时传 getter、setter
创建一个可手动修改的计算状态。

<template>
  <div>
    <h1>computed - 计算属性</h1>
    <p>firstname: <input v-model="user.firstname" /></p>
    <p>lastname: <input v-model="user.lastname" /></p>
    <p>username: <input v-model="username" /></p>
  </div>
</template>

<script>
import { reactive, computed } from "vue";
export default {
  name: "Computed2",
  setup() {
    const user = reactive({ firstname: "Chen", lastname: "Haihong" });
    const username = computed({
      get: () => user.firstname + " " + user.lastname,
      set: (value) => {
        const [firstname, lastname] = value.trim().split(" ");
        user.firstname = firstname;
        user.lastname = lastname;
      },
    });
    return { user, username };
  },
};
</script>

watchEffect、watch - 侦听器

watchEffect
立即执行传入的一个函数,并响应式追踪其依赖,并在其依赖变更时重新运行该函数。

<template>
  <div>
    <h1>watchEffect - 侦听器</h1>
    <p>{{data.count}}</p>
  </div>
</template>

<script>
import { reactive, watchEffect } from "vue";
export default {
  name: "WatchEffect",
  setup() {
    const data = reactive({ count: 1 });
    watchEffect(() => console.log(`侦听器:${data.count}`));
    setInterval(() => {
      data.count++;
    }, 1000);
    return { data, stop };
  },
};
</script>

watch
对比watchEffect,watch允许我们:
• 懒执行副作用,也就是说仅在侦听的源变更时才执行回调;
• 更明确哪些状态的改变会触发侦听器重新运行副作用;
• 访问侦听状态变化前后的值。

<template>
  <div>
    <h1>watch - 侦听器</h1>
    <p>count1: {{data.count1}}</p>
    <p>count2: {{data.count2}}</p>
    <button @click="stopAll">Stop All</button>
  </div>
</template>

<script>
import { reactive, watch } from "vue";
export default {
  name: "Watch",
  setup() {
    const data = reactive({ count1: 0, count2: 0 });
    // 侦听单个数据源
    const stop1 = watch(data, () =>
      console.log("watch1", data.count1, data.count2)
    );
    // 侦听多个数据源
    const stop2 = watch([data], () => {
      console.log("watch2", data.count1, data.count2);
    });
    setInterval(() => {
      data.count1++;
    }, 1000);
    return {
      data,
      stopAll: () => {
        stop1();
        stop2();
      },
    };
  },
};
</script>

readonly - “深层”的只读代理

传入一个对象(响应式或普通)或 ref,返回一个原始对象的只读代理。一个只读的代理是“深层的”,对象内部任何嵌套的属性也都是只读的。

<template>
  <div>
    <h1>readonly - “深层”的只读代理</h1>
    <p>original.count: {{original.count}}</p>
    <p>copy.count: {{copy.count}}</p>
  </div>
</template>

<script>
import { reactive, readonly } from "vue";

export default {
  name: "Readonly",
  setup() {
    const original = reactive({ count: 0 });
    const copy = readonly(original);

    setInterval(() => {
      original.count++;
      copy.count++; // 报警告,Set operation on key "count" failed: target is readonly. Proxy {count: 1}
    }, 1000);


    return { original, copy };
  },
};
</script>

toRef - 为 reactive 对象的属性创建一个 ref

toRef 可以用来为一个 reactive 对象的属性创建一个 ref。这个 ref 可以被传递并且能够保持响应性。

setup() {
  const user = reactive({ age: 1 });
  const age = toRef(user, "age");

  age.value++;
  console.log(user.age); // 2

  user.age++;
  console.log(age.value); // 3
}

当您要将一个 prop 中的属性作为 ref 传给组合逻辑函数时,toRef 就派上了用场:

export default {
  setup(props) {
    useSomeFeature(toRef(props, 'foo'))
  },
}

toRefs - 解构响应式对象数据

把一个响应式对象转换成普通对象,该普通对象的每个 property 都是一个 ref ,和响应式对象 property 一一对应。

<template>
  <div>
    <h1>解构响应式对象数据</h1>
    <p>Username: {{username}}</p>
    <p>Age: {{age}}</p>
  </div>
</template>

<script>
import { reactive, toRefs } from "vue";

export default {
  name: "DestructReactiveObject",
  setup() {
    const user = reactive({
      username: "haihong",
      age: 10000,
    });

    return { ...toRefs(user) };
  },
};
</script>

isRef、isProxy、isReactive、isReadonly

检查一个值/对象是否为一个 ref / proxy / reactive / readonly 对象。

你可能感兴趣的:(vue,前端,vue,javascript,vue.js)