[路飞]_初识vue3

113 阅读3分钟

对vue3 新增的api 称为 composition API, 同时也保留了大部分vue2的api称为 options API

对vue3的初步使用最直观的体验就是几乎没有看见this的身影,其次就是纯函数式的写法带来的快感

首先创建vue3的项目,可以用vue-cli 中的 vue create xxx 去创建,模版直接选用vue3即可

先看看 main.js 文件

// vue3版
import { createApp } from "vue";
import App from "./App.vue";
createApp(App).mount("#app");
// vue2版
import Vue from 'vue'
import App from './App.vue'
Vue.config.productionTip = false
new Vue({
  render: h => h(App),
}).$mount('#app')

tree-shaking —————— vue3减少了实例这个操作,这个只是优化了用户的体验,关键在于对vue的引入,在vue2版本中,vue是整个引入的,这对最后的项目打包时是占有固定的体积的,vue3在这方面看出来做了优化,通过“按需引入”的概念进行引入,这便可以初步控制打包的大小

App.vue

// vue3版
<template>
  <img alt="Vue logo" src="./assets/logo.png" />
  <HelloWorld msg="Welcome to Your Vue.js App" />
</template>

// vue2版
<template>
  <div id="app">
    <img alt="Vue logo" src="./assets/logo.png">
    <HelloWorld msg="Welcome to Your Vue.js App"/>
  </div>
</template>

这里明显看到对根结点有做不一样的处理,通过翻阅官方文档了解到 vue3中对fragment

接着又发现一个有意思的 composition API ———— teleport 我先文字描述一下一个经常使用的业务场景,就是在后台管理系统中常常会有弹框在组件生态中叫模态框,那vue2中的实现由于实例中都是加载中根元素app下,如果app的添加了position:relative;此样式,那么模态框就会以app来做相对参照物去进行位移,所以在vue2要特别注意根元素的样式设置; 那么在vue3中提供了teleport 这个api去避免这个问题,说白了就是模态框这个组件创建在了根元素外的结点,并没有在根元素里面,所以即使根元素有相关的样式变更也不受影响

image.png

使用方法就是用teleport当作标签 并在to属性中表明所要创建在那个标签下

const app = Vue.createApp({});

app.component('modal-button', {
  template: `
    <button @click="modalOpen = true">
        Open full screen modal! (With teleport!)
    </button>

    <teleport to="body">
      <div v-if="modalOpen" class="modal">
        <div>
          I'm a teleported modal! 
          (My parent is "body")
          <button @click="modalOpen = false">
            Close
          </button>
        </div>
      </div>
    </teleport>
  `,
  data() {
    return { 
      modalOpen: false
    }
  }
})

app.mount('#app')

接下来进入常用的 composition API

setup ———— 可以理解为几乎所有逻辑行为定义都可以往这里加

ref ———— 创建响应式对象 通过创建ref 如果创建的是引用类型的 其实就是创建的ref对象中使用用了proxy代理

<template>
    <div>
        {{count}}
        <button @click="handleCount">click<button/>
    </div>
</template>

<script>
import { ref } from "vue"
export default {
  setup() {
      // 创建响应式对象
      let count = ref(1);
      // 更改count事件 
      function handleCount() {
           count.value++; 
      }
      
      // 暴露响应式数据 与 定义的方法
      return {
          count,
          handleCount
      }
  }
}

reactive ———— 创建响应式对象 通过Proxy 代理

<template>
    <div>
        {{countObj.name}}:{{countObj.count}}
        <button @click="handleCount">click<button/>
    </div>
</template>

<script>
import { ref } from "vue"
export default {
  setup() {
      // 创建响应式对象
      let countObj = reactive({
          name:"xx"
          count:1
      });
      // 更改count事件 
      function handleCount() {
           countObj.count++; 
      }
      
      // 暴露响应式数据 与 定义的方法
      return {
          countObj,
          handleCount
      }
  }
}

readonly ———— 创建一个不可修改的响应式对象 与上述创建语法一致 props ———— 父子组件传值

<template>
    <div>
        child
    </div>
</template>

<script>
import { ref } from "vue"
export default {
  props:['title']
  setup(props) {
      // props 就是title就是在父组件中的属性,props即可接收到  注意props中不可修改
  }
}

computed watch 实际上都变成了函数式的调用方式

<template>
    <div>
        child
    </div>
</template>

<script>
import { ref } from "vue"
export default {
  setup() {
    let count = ref(1);
    let double = computed(()=>{
        return count.value * 2
    })
    // 需要监听的数据,回调函数,其它可设置参数 
    
    watch(count, (newVal, oldVal) => {
        // todo soming
    },{
        immediate:true,
    })
    const user = reactive({
        use:"xx",
        age:18
    })
    // 引用类型某个属性
    watch(() => user.age, (newVal, oldVal) => {
        // todo soming
    },{
        immediate:true,
    })
    
    // 如果监听整个对象 需要对这个对象进行深克隆,不然无法响应 这里deepclone可以自己实现可以使用loadsh库等深克隆的方法
    watch(()=> deepclone(user),(newVal, oldVal) => {
        // todo soming
    })
  }
}

watchEffect ———— 跟watch使用大致相同,但无需具体指定监听谁

watchEffect((onInvalidate)=>{
    onInvalidate(()=>{
        // 在watchEffect被调用时会触发,使用组件被销毁时也会触发
    })
    // 在这里进行依赖收集,如果收集的依赖中有发生值的改变则会触发
},{
    flush:"pre" // 默认值为pre 在组件render之前调用,post 在组件render之后调用
})

provide , inject ———— 依赖注入 设置值的组件 provide('属性名','属性值')

获取值的组件中 inject('属性名','默认值')