Vue3入门

172 阅读2分钟

Vue3安装

Vue-cli脚手架:npm install -g @vue/cli -----> vue create

Vite:npm install vite-app

Vue3新特性

Composition API、自定义Hooks、生命周期钩子、Teleport、Suspense(带插槽的组件)、Fragment(代码多个片段)、Tree-Shaking(nextTick)

Composition API

reactive、ref、toRefs、watch、watchEffect、computed、生命周期钩子 使用setup时,它接受两个参数: 1.props:组件传入的属性 2.context:attrs、slot 和emit

ref能处理 js 基本类型,也可以定义对象的双向绑定 reactive函数确实可以代理一个对象, 但是不能代理基本类型 toRefs用于将一个reactive对象转化为属性全部为 ref 对象的普通对象

watch 函数用来侦听特定的数据源,并在回调函数中执行副作用。默认情况是惰性的,也就是说仅在侦听的源数据变更时才执行回调。

watch(source, callback, [options])
  • source: 可以支持 string,Object,Function,Array; 用于指定要侦听的响应式变量
  • callback: 执行的回调函数
  • options:支持 deep、immediate 和 flush 选项。

侦听 reactive、ref 定义的数据

import { defineComponent, ref, reactive, toRefs, watch } from "vue";
export default defineComponent({
  setup() {
    const state = reactive({ 
      nickname: "xiaofan",
      age: 20,
      room: {
        id: 100,
        attrs: {
          size: "140平方米",
          type: "三室两厅",
        },
      }
    });
    const year = ref(0);
    setTimeout(() => {
      state.age++;
      year++;
    }, 1000);
    // 修改age、year值时会触发 watch的回调
    watch([() => state.age, year,() => state.room], ([curAge, newVal], [preAge, oldVal],[preAge1,oldVal2]) => {
      console.log("新值:", curAge, "老值:", preAge); 
      console.log("新值:", newVal,"老值:", oldVal); 
    },{ deep: true });
    return {
      ...toRefs(state),
    };
  },
});

watchEffect

import { defineComponent, ref, reactive, toRefs, watchEffect } from "vue";
export default defineComponent({
  setup() {
    const state = reactive({ nickname: "xiaofan", age: 20 });
    let year = ref(0)
    setInterval(() =>{
        state.age++
        year.value++
    },1000)
    watchEffect(() => {
        console.log(state);
        console.log(year);
      }
    );
    return {
        ...toRefs(state)
    }
  },
});
  1. watchEffect 不需要手动传入依赖
  2. watchEffect 会先执行一次用来自动收集依赖
  3. watchEffect 无法获取到变化前的值, 只能获取变化后的值
Teleport

即希望继续在组件内部使用Dialog, 又希望渲染的 DOM 结构不嵌套在组件的 DOM 中。 此时就需要 Teleport 上场,我们可以用<Teleport>包裹Dialog, 此时就建立了一个传送门,可以将Dialog渲染的内容传送到任何指定的地方。

// index.html
<body>
  <div id="app"></div>
  <div id="dialog"></div>
</body>
// Dialog.vue
<template>
  <teleport to="#dialog">
    <div class="dialog">
      <div class="dialog_wrapper">
        <div class="dialog_header" v-if="title">
          <slot name="header">
            <span>{{ title }}</span>
          </slot>
        </div>
      </div>
      <div class="dialog_content">
        <slot></slot>
      </div>
      <div class="dialog_footer">
        <slot name="footer"></slot>
      </div>
    </div>
  </teleport>
</template>
vue2与vue3
Object.defineProperty与Proxy
  1. Object.defineProperty只能劫持对象的属性, 而Proxy是直接代理对象 由于Object.defineProperty只能劫持对象属性,需要遍历对象的每一个属性,如果属性值也是对象,就需要递归进行深度遍历。但是Proxy直接代理对象, 不需要遍历操作
  2. Object.defineProperty对新增属性需要手动进行Observe 因为Object.definePropert劫持的是对象的属性,所以新增属性时,需要重新遍历对象, 对其新增属性再次使用Object.defineProperty进行劫持。也就是Vue2.x中给数组和对象新增属性时,需要使用set才能保证新增的属性也是响应式的,set才能保证新增的属性也是响应式的, set内部也是通过调用Object.defineProperty去处理的。