Vue 3.0 入门基础总结

setup

组件选项,在组件创建之前执行,一旦 props 被解析,就将作为组合式 API 的入口

参数
  • props
  1. 所有声明了的 prop,不管父组件是否向其传递了,都将出现在 props 对象中。其中未被传入的可选的 prop 的值会是undefined。
  2. setup 函数中的 props 是响应式的,当传入新的 prop 时,它将被更新,所以不能使用 ES6解构,会消除 prop 的响应性
  3. 如果需要解构 prop,可以在 setup 函数中使用 toRefs 函数来完成此操作
  4. 如果某个属性是可选的 prop,则传入的 props 中可能没有该属性。在这种情况下,toRefs 不适用 。需要使用 toRef 替代。
  • context
  1. context.attrs —— // Attribute (非响应式对象,等同于 $attrs)
  2. context.slots —— // 插槽 (非响应式对象,等同于 $slots)
  3. context.emit —— // 触发事件 (方法,等同于 $emit)
  4. context.expose —— // 暴露公共 property (函数)
使用注意点
  1. setup 的调用发生在 data property、computed property 或 methods 被解析之前,就说在 setup函数中是无法 使用 data 和 methods 中的数据和方法的
  2. 在setup函数中定义的变量和方法最后都是需要 return 出去的,不然无法再模板中使用
  3. setup函数只能是同步的不能是异步的
  4. 生命周期钩子函数只能写在setup中
  5. provide/inject 只能写在setup中

 
 
 
 

ref和reactive

ref
  • 在 Vue 3.0 中,通过ref 函数使任何响应式变量在任何地方起作用。即ref 为我们的值创建了一个响应式引用,访问时需要通过.value进行访问
reactive
  • 返回对象的响应式副本
  • reactive 将解包所有深层的 refs,同时维持 ref 的响应性
const count = ref(1)
const obj = reactive({ count })

// ref 会被解包
console.log(obj.count === count.value) // true
  • 当将 ref 分配给 reactive property 时,ref 将被自动解包
const count = ref(1)
const obj = reactive({})

obj.count = count

console.log(obj.count) // 1
console.log(obj.count === count.value) // true
用法示例
 <script>
   import { ref, reactive } from "vue";
   setup(){
     const str = ref("vue3.0")
     const obj = reactive ({name: '张三', age: 20})
     function changeStr(){
       str.value = "vue3.0牛逼"
     }
     function changeObj(){
       obj.name= "李四"
     }
     return { str, obj, changeStr, changeObj }
   }
 </script>
区别

ref 和 reactive 本质我们可以简单的理解为ref是对reactive的二次包装, ref定义的数据访问的时候要多一个.value

  1. ref定义的数据需要通过.value才能使用,而reactive则不需要
  2. ref返回RefImpl对象(也叫ref对象),reactive返回Proxy对象。
  3. ref可以为基本类型添加响应式,也可以为引用类型添加响应式,reactive只能为引用类型添加响应式。
    ps:只打算修改引用类型的一个属性,那么推荐用reactive,如果你打算变量重赋值(改变整个对象),那么一定要用ref。

原因在于jsonData尽管是响应式的,但是响应式的是它的属性,而不是它自身,重赋值它自身跟重赋值它的属性是两码事。所以,想在组合式API中让数据具备响应式,必须用ref,因为ref又对Proxy包装了一层,修改ref其实是修改它的value,它的value一定是响应式的,因此视图就正常更新了

更多详细讲解 https://www.jianshu.com/p/cfe25e757d0e

 
 
 
 

Provide / Inject

通常当我们需要将数据从父组件传递到子组件时,我们通过props实现。 设想一下这样的一个组件结构,这个结构中有一些嵌套层级很深的组件,我们想在内嵌层级很深的一个子组件中,调用顶层父组件的某些数据。在这种情况下,如果我们仍需要通过prop从父组件到子组件之间的组件链中传递数据,会进行很多次传递,这可能挺烦人的。

为了应对这种情况,我们可以使用provide与inject的组合。父组件可以无视组件层级的深度,作为所有子组件的依赖提供者。这个特性基于两部分:父组件通过provide选项提供数据,并且子组件通过inject选项使用所提供的数据。

provide

使用 provide 时,首先需要从 vue 显式导入 provide 方法
provide 函数定义property接收两个参数:

  • name ( 类型)
  • value
inject

使用 inject 时,也需要从 vue 显式导入
inject函数有两个参数:

  • 要 inject 的 property 的 name
  • 默认值 (可选)

ps:provide/inject 只能写在setup中,即不能写在异步函数和回调函数中,因为那时已经不在setup生命周期中了

用法

父组件
<template>
  <div class="parent">
    <h1>父组件的值:{{ primaryValue }}</h1>
    <button @click="changeFatherValue(88)">父组件的值改变</button>
    <chidCom></chidCom>
  </div>
</template>

<script>
import chidCom from "../components/childCom.vue";
import { ref, reactive, provide } from "vue";
export default {
  components: {
    chidCom,
  },
  setup() {
    let primaryValue = ref(4);
    let objectValue = reactive({
      name: "pzp",
      age: "23",
    });
    provide("primaryValue", primaryValue);
    provide("objectValue", objectValue);

    console.log(primaryValue.value, objectValue.name);

    let changeFatherValue = (val) => {
      primaryValue.value = val;
      objectValue.name = "pzpa";
    };
    provide('changeFatherValue', changeFatherValue)

    return {
      primaryValue,
      objectValue,
      changeFatherValue,
    };
  },
  //   methods: {
  //       changeFatherValue() {
  //           this.primaryValue = 8
  //           this.objectValue.name = 'pzpa'
  //       },
  //   },
};
</script>
子组件
<template>
  <div>
    <h1>父组件注入基础类型值:{{ fatherPrimary }}</h1>
    <h1>父组件注入对象类型值:{{ fatherObject.name }}</h1>
    <button @click="changeFatherValue(66)">子组件改变父组件值</button>
  </div>
</template>

<script>
import { inject } from "vue";
export default {
  setup() {
    let fatherPrimary = inject("primaryValue");
    let fatherObject = inject("objectValue");
    let changeFatherValue = inject('changeFatherValue')

    return {
      fatherPrimary,
      fatherObject,
      changeFatherValue
    };
  },
};
</script>
效果展示

Vue 3.0 入门基础总结_第1张图片

注意点
  • 若需要provide/inject传递的值有响应性,被传递值的定义必须通过ref/reactive进行定义
  • 当使用响应式 provide / inject 值时,建议尽可能将对响应式 property 的所有修改限制在定义 provide 的组件内部,即尽量在父组件内进行修改。若需要在子组件更新注入的数据,建议 provide 一个方法来负责改变响应式 property,比如上面的changeFatherValue
  • 如果要确保通过 provide 传递的数据不会被 inject 的组件更改,建议对提供者的 property 使用 readonly

 
 
 
 

getCurrentInstance

官文给出的该方法的描述为:getCurrentInstance 支持访问内部组件实例。特别强调了

getCurrentInstance 只暴露给高阶使用场景,典型的比如在库中。强烈反对在应用的代码中使用 getCurrentInstance。请不要把它当作在组合式 API 中获取 this 的替代方案来使用

使用方法详解

 
 
 
 

计算属性-computed

计算属性和方法的区别

接受一个 getter 函数,并根据 getter 的返回值返回一个不可变的响应式 ref 对象

const count = ref(1)
const plusOne = computed(() => count.value + 1)

console.log(plusOne.value) // 2

plusOne.value++ // 错误

或者,接受一个具有 get 和 set 函数的对象,用来创建可写的 ref 对象。

const count = ref(1)
const plusOne = computed({
  get: () => count.value + 1,
  set: val => {
    count.value = val - 1
  }
})

plusOne.value = 1
console.log(count.value) // 0

 
 
 
 

监听器-watch

侦听器数据源可以是返回值的 getter 函数,也可以直接是 ref

侦听单个数据源
// 侦听一个 getter
const state = reactive({ count: 0 })
watch(
  () => state.count,
  (count, prevCount) => {
    /* ... */
  }
)

// 直接侦听ref
const count = ref(0)
watch(count, (count, prevCount) => {
  /* ... */
})
侦听多个数据源
const firstName = ref('')
const lastName = ref('')

watch([firstName, lastName], (newValues, prevValues) => {
  console.log(newValues, prevValues)
})

firstName.value = 'John' // logs: ["John", ""] ["", ""]
lastName.value = 'Smith' // logs: ["John", "Smith"] ["John", ""]

ps:在同一个函数里同时改变这些被侦听的来源,侦听器仍只会执行一次,即多个同步更改只会触发一次侦听器

侦听响应式对象(深度嵌套对象)

 
 
 
 

useStore

在Vue3中,不能通过this.$store来获取使用vuex中存储的值,并且也不能使用getCurrentInstance来替代this进行使用。
此时若需要获取vuex的实例,就需要用到useStore方法
ps:同理,对于路由的使用也是通过useRouteuseRouter 方法

import { useRoute, useRouter } from "vue-router"
import { useStore } from 'vuex'

setup(props, context) {
     // vue 3.0中vuex的使用
     let store = useStore()
     let storeValue = computed(() => store.state.user)
     
     return {
         storeValue
     }
 }

 
 
 
 

虚拟dom算法更新

  • vue3修改了虚拟dom的算法(即diff算法 - 比对虚拟dom有没有变化)
  • vue2需要diff所有的虚拟dom节点,而vue3参考了SVELTE框架的思想,先分层次-然后找不变化的层-针对变化的层进行diff,更新速度不会再受template大小的影响,而是仅由可变的内容决定。经过尤雨溪自己的测试,大概有6倍的速度提升。

 
 
 
 

数据的双向绑定

关于数据双向绑定的实现,vue2 采用了defineProperty,而vue3则采用了proxy。

优点:

  • 使用proxy不污染源对象,会返回一个新对象,defineProperty是注入型的,会破坏源对象
  • 使用proxy只需要监听整个源对象的属性,不需要循环使用Object.defineProperty监听对象的属性
  • 使用proxy可以获取到对象属性的更多参数,使用defineProperty只能获取到监听属性的新值newvalue
/* vue2.0*/
var a = { b: 123, c: 444 };
Object.defineProperty(a, "b", {
  set: function (newvalue) {
    console.log("i am be set");
  },
}); //只能获取到newvalue这个参数

/* vue3.0 */
var a = { b: 123, c: 444 };
var newa = new Proxy(a, {
  set: function (target, key, newvalue) {
    console.log(target, key, newvalue);
  },
}); //可以获取到target,key,newvalue三个参数

 
 
 
 

生命周期钩子

Vue 3.0 入门基础总结_第2张图片

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