vue3.0实用体验总结

212 阅读6分钟

vue3.0来临,这些必须得会啦!

新特性

Performance

  • 重写了虚拟DOM的实现(跳过静态节点,只处理动态节点)
  • update性能提供1.3~2倍
  • SSR速度提供了2~3倍

Tree shaking

  • 可以将无用模块“剪辑”, 仅打包需要的

Fragment

  • 不再限于模板中的单个节点
  • 类似于react里的空节点<></>
<template>
  <p> Count: {{ count }} </p>
  <button @click="increment"> Increment </button>
  <button @click="decrement"> Decrement </button>
</template>

<teleport>

  • 将组件中渲染到页面任意一个 DOM 节点中
  • 以前称为, 传送门, Alpha版本暂不能使用
  • vue2是利用第三方插件完成的
 <Teleport to="#modal-layer">
   <div class="modal">hello</div>
 </Teleport>

<Suspense>

  • 可在嵌套层级中等待嵌套的异步依赖项

  • 通常前后端交互是一个异步的过程: 默认我们提供一个加载中的动画,2.x版本我们通常用 v-if 来控制数据显示

  • 这个还是比较实用的

    <template>
    <Suspense>
      <template #default>
        异步返回的数据
      </template>
      <template #fallback>
        loading...
      </template>
    </Suspense>
    
```

TypeScript

  • 更好的TypeScript支持

Custom Renderer API

  • 自定义渲染器API
  • 用户可以尝试WebGL自定义渲染器

Composition API

  • 成为组合式API,替换原有的Options API
    1. 根据逻辑相关性组织代码,提供可读性和可维护性
    2. 更好的重用逻辑代码(避免mixins混入时命名冲突的问题)
  • 但是依然可以延用Options API
  • 这个对于使用是最大的变动

在2.0时代我们要把代码写到指定位置,我们理解为配置到指定的options ,称为Options API, 我们发现在项目代码少的情况下代码很清晰,如果代码量比较多就不太利于我们可读性维护性了,尤大大收到了这样的吐糟,预算3.0提供了componsition Api 称之为组合式API, 提供了一个setup, 是整个api的入口。 把特定功能的模块导入到setup里面,统一暴露出去来使用。

Proxy

  • 响应式原理不再基于Object.defineProperty

基于vue/cli 配置3.0

github.com/vuejs/vue-n… vue-cli-plugin-vue-next vue-cli 版本需要> 4.3.1

 npm install -g @cli/cli
 vue --version
  vue create xxx
 vue add vue-next

基于vite配置3.0 -个人推荐

由作者you雨溪开发的web开发工具 github.com/vitejs/vite

  • 基于浏览器原生ES imports的开发服务器(利用浏览器去解析imports, 在服务器端按需编译返回,完全跳过了打包这个概念,服务器随起随用) 同事不仅有Vue文件支持,还搞定了热更新,而且热更新的速度不会随着模块而变慢
npm init vite-app xxx
cd xxx
npm install
npm run dev
npm run build

掌握setup和响应式系统API

参见:vue-composition-api-rfc.netlify.app/zh/api.html

setup

setup 函数是一个新的组件选项,作为在组件内使用Composition API的入口点

  • 初始化props和beforeCreate之间调用
  • 可以接收props和context
  • this在setup()中不可用

props是响应式的,可以基于watchEffect、watch监听,解构赋值后则无效

import { watchEffect } from 'vue';
export default {
    props: {
        title: String
    },
    // 初始化props和beforeCreate之间
    setup(props) {
        // props: 基于Proxy响应式数据
        console.log(props);
        watchEffect(() => {
            console.log('title is:' + props.title)
        })
    }
}

ref

接收一个参数值并返回一个响应式且可改变的ref对象

  • ref对象拥有一个指向内部值的单一属性.value
  • 当ref在模板中使用的时候,它会自动解套,无需在模板内部额外书写value
  • 一般处理
import { ref } from 'vue';
export default {
    props: {
        title: String
    },
    setup(props) {
        // 构建响应式数据 一版处理简单值得响应式 原理:defineProperty
        let supNum = ref(0),
        oppNum = ref(0);
        console.log(supNum);
        console.log(supNum.value)
        function change(lx) {
            lx == 0? supNum.value++: oppNum.value++;
        }
        return {
            supNum,
            oppNum,
            change
        }
    }
}

控制台输出:

reactive

接受一个普通对象然后返回该普通对象的响应式数据 等同于2.x Vue.observable()

  • 响应式转换是“深层的”, 会影响对象内所有嵌套的属性
  export default {
    setup(props) {
          // 响应式构建方案 reactive 基于Proxy数据深度的监听,以此构建响应式
          let state = reactive({
              supNum: 0,
              oppNum: 0,
  			  arr: [1020]
          });
  		
  		function change() {
            state.arr[2] = 30; // 直接修改值
  			state.sum = 40;  // 新增属性
        }
  		
  		return {
            state,
            change,
        }
    }
  }

unref/toRef/toRefs/isRef/isProxy/isReactive/isReadonly

toRef/toRefs

把reactive 种每一项变为ref响应式数据 template 下可以直接使用

setup() {
  let state = reactive({
    supNum: 0,
    oppNum: 0
    });

    console.log('toRef:', toRef(state, 'supNum')); // 转单一属性
    console.log('toRefs:', toRefs(state)); // 转所有属性
    return {
    	state
    }
}

readonly

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

setup(props) {
     let xxxObj = reactive({
          x: 10,
          y: {
              z: 20
          }
      })
      let xxxObj2 = readonly(xxxObj);
      console.log(xxxObj2.y.z); // 修改会触发xxxObj2上的监听
  	
      xxxObj2.y.z = 100; // 无法修改会被警告
		return {
          xxxObj
      }
  

警告如图:

computed

传入一个getter函数,返回一个默认不可手动修改的ref对象

 let count = ref(1);
 let plusOne = computed(() => count.value+1)
 console.log(plusOne.value) // 2
 plusOne.value++; // 错误

或者传入一个拥有get 和 set 函数的对象,创建一个可手动修改的计算属性

	const  count = ref(1);
	let plusOne = computed({
    get: () => count.value + 1,
    set: val => {
    	count.value = val -1;
    }
	})
  plugOne.value = 1;
	console.log(count.value); //0

watchEffect

立即执行传入一个函数,并响应式追踪其依赖,并在其依赖变更时重新运行该函数 类似于2.x的watch 下的immediate: true

import { watchEffect } from 'vue';
export default {
  props: {
  title: String
  },
  setup(props) {
    watchEffect(() => {
        console.log('title is:' + props.title)
    })
  }
}

watch

watch Api完全等效于2.x this.$watch

  • watch 需要监听特定的数据源, 并在回调函数中执行副作用
  • 默认情况下是懒执行的,也就是说仅在监听的源变更时才执行回调
...
setup(props) {
		let state = reactive({
          supNum: 0,
          oppNum: 0
      })
		// 写法1:
		watch(state, () => {
          console.log(state.supNum);
      })

      // 写法2: 只监听state下的supNum, 需要这样写
      watch(
          () => state.supNum, 
          () => {
          console.log(state.supNum);
          }
      )

      let x = ref(0),
      y = ref(0);
		// 写法3:监听多个
      watch([x, y], ([x, y], [prevX, prevY]) => {
          console.log(x, prevX);
          console.log(y, prevY);
      })
	...
}

模板refs

当使用组合式API时,reactive refs 和 template refs 的概念是一样的 和2.x 那个一样, 就是取dom节点的

<template>
  <div ref="root"></div>
</template>
<script>
import { ref, onMounted } from 'vue';
export default {
  props: {
      title: String
  },
  setup(props) {
      
      const root = ref(null);
      onMounted(() => {
          console.log(root.value);
      })
      return {
          root
      }
  }
}
</script>

声明周期函数

可以直接导入onXXX 一族的函数来注册生命周期钩子

  • 这些生命周期钩子注册函数只能在sestUp()期间同步使用
  • 在卸载组件时,生命周期钩子内部同步创建的监听器和计算状态也将删除 2.x版本 -> 3.0版本对照
  • beforeCreated -> 使用setup()
  • created -> 使用setup()
  • beforeMount -> 使用setup()
  • mounted -> onMounted
  • beforeUpdate -> onBeforeUpdate
  • update -> onUpdated
  • beforeDestory -> onBeforeUnmount
  • destoryed -> onUnmounted
  • errorCaptured -> onErrorCaptured

v3.0使用哪个api,就引入哪个,打包时也将只打包使用过的api. 更轻便

  • 如果想在2.x中体验vue3.0 ,可以通过@vue/omposition这个库。

与 React Hooks 相比

基于函数的组合式 API 提供了与 React Hooks 同等级别的逻辑组合能力,但是与它还是有很大不同:组合式 API 的 setup() 函数只会被调用一次,这意味着使用 Vue 组合式 API 的代码会是:

  • 一般来说更符合惯用的 JavaScript 代码的直觉;

  • 不需要顾虑调用顺序,也可以用在条件语句中;

  • 不会在每次渲染时重复执行,以降低垃圾回收的压力;

  • 不存在内联处理函数导致子组件永远更新的问题,也不需要 useCallback;

  • 不存在忘记记录依赖的问题,也不需要“useEffect”和“useMemo”并传入依赖数组以捕获过时的变量。Vue 的自动依赖跟踪可以确保侦听器和计算值总是准确无误。