01—Vue3.0开发初体验

315 阅读2分钟

前置知识:Vue3.0带来的变化

  • 使用monorepo的形式来管理源代码
  • Vue2.0使用flow进行类型检测,Vue3.0源码使用Typescript来进行重写
  • 性能方面:Vue2.0使用Object.defineProperty来劫持,无法监听给对象添加/删除的属性.Vue3.0使用Proxy进行数据劫持,
  • 由Options API到Composition API,数据管理更加清晰
  • 通过hooks实现代码的共用性,Vue2.0使用mixin来共享代码

初次体验Vue3.0

引入Vue3.0

  • CDN(通过互联网共享网络,使用最靠近每个用户的服务器)引入
    • CDN服务器:阿里,腾讯,亚马逊,Google等
    • 开源服务器:unpkg,JSDelivr,cdnjs
    • <script src="https://unpkg.com/vue@next"></script>
  • 下载Vue的文件,手动导入
  • NPM下载安装
  • Vue Cli自动导入
<script src="https://unpkg.com/vue@next"></script>
<script>
    let tempObj = {
        template: `<h2>Hello World~</h2>`,
    }
    const App = Vue.createApp(tempObj)
    App.mount('#app');
</script>

使用Vue和原生JavaScript对比实现一个计数器 image.png image.png

查看Vue3.0源码

  • 查看方式github搜索vue-next
  • tags选择v3.2.0版本, git clone到本地
  • 安装本地依赖,yarn install, 本地运行yarn run dev
  • package.json的「dev」开启--sourcemap,方便直接定位到相对应的源代码文件
  • 通过debugger的形式查看源码

image.png

Composition API

setup传递2个参数,propscontext:

  • props 为父组件的数据传值
  • context 执行上下文
    • attrs
    • slot
    • emit
import {ref} from "vue";
setup(){
    const counter = ref(10); //counter的ref的引用值,Vue可以实现自动解包的过程.页面可以直接绑定counter的引用值
    const increment = ()=>{
        counter.value++;
    }
    return {
        counter,
        increment
    }
}

////////////////////////////
import {reactive} from "vue";
setup(){
    const counter = reactive({count:10});
    const increment = ()=>{
        counter.count++;
    }
    return {
        counter,
        increment
    }
}

实现Vue3.x中的数据响应式数据如果是复杂数据使用reactive,如果复杂变量传入简单变量的话系统会报警告,reactive直接修改对象里面的属性,简单变量是用ref是作为响应式的引用维护着它内部的值,简单变量修改.value属性修改具体内部的值。

readonly会返回原生对象的只读代理,proxy会对set方法进行数据劫持.

自定义Ref

<template>
    <div>
        <h1 ref="titleDOM"></h1>  //获取原生DOM
    </div>
</template>

//定义hooks
import { customRef } from "vue";
export default function (value, delay=300) { //默认为300ms,可以设置时间,自定义hooks第二个参数即可
  let timer = null;
  
  return customRef((track, trigger) => {
    return {
      get() {
        track();
        return value;
      },
      set(newValue) {
        clearTimeout(timer);
        timer = setTimeout(() => {
          value = newValue;
          trigger();
        }, delay);
      },
    };
  });
}

//引入代码
<template>
  <div>
    <input type="text" v-model="inputValue" /> <br />
    {{ inputValue }}
  </div>
</template>

<script>
import debounce from "./hooks/useDebounce";
export default {
  props: {
    message: {
      type: String,
      required: true,
    },
  },
  setup() {
    let titleDOM = ref(null); //默认绑定title的DOM
    const inputValue = debounce();
    return {
      inputValue,
      titleDOM
    };
  },
};
</script>

computed

computed默认是一个ref对象,需要修改其内部.value的值

let firstName = ref('hello');
let lastName = ref('hello');
let fullName = computed(()=>{}
    return firstName.value+lastName.value;
)

watch / watchEffect 监听数据变化

watchEffect会自动监听数据变化,会默认执行一次作为自动执行的依赖。

//当年龄大于25时,停止watchEffect的监听
const stopAddAge = watchEffect((onInvalidate) => {
  onInvalidata(()=>{
      console.log("清除副作用...");
  })
  
  console.log("年龄:", age.value);
  
});
function handleAgeAdd() {
  age.value++;
  if (age.value > 25) {
    stopAddAge();
  }
}

watch相比较于watchEffect是懒执行的

let info = reactive({name:"huangfl"})
//监听reactive对象的某一个属性值时,reactive监听变化需要进行转换
watch(()=>info.name, (newValue, oldValue)=>{
    console.log(newValue, oldValue);
})

//监听整个reactive对象
watch( info, (nv, ov)=>{
    console.log(nv, ov);
})

watch监听多个数据源

//适用于监听reactive类型的数据
watch([name, info],([oldName, newName], [oldInfo, newInfo])=>{
    console.log(oldName, newName, oldInfo, newInfo); 
})