vue3.0学习(一)

285 阅读6分钟

创建应用实例

vue3.0创建vue实例不再通过new Vue()方式创建,而是通过createApp工厂函数创建。

该应用实例是用来在应用中注册“全局”组件。

应用实例暴露的大多数方法都会返回该同一实例,允许链式。

createApp需要引入才能使用。

import { createApp } from 'vue'
import App from './App.vue'
import son from './components/son.vue'
createApp(App).component('son', son).mount('#app')

setup([props],[context])

setup是vue3新增加的配置项,在模版中使用的数据和方法都要在此方法中返回才能使用。

setup执行时间在beforeCreate()生命周期之前。

setup有两种返回结果:

  1. 返回对象,只有在该对象中返回的数据和方法才能在模版中使用。
  2. 返回一个渲染函数。它会替代模版作为渲染界面结果。
<template>
    <h1>123445</h1>
    <h1>{{ name }}</h1>
    <button @click="changeVal">点击</button>
</template>
<script>
import { ref, h } from 'vue'
export default {
    setup() {
        let name = ref('1')
        console.log(name)
        function changeVal(){}
        return { name,changeVal }
        // return () => h('h1', { style: { color: 'red' } }, '这是渲数')
    }
}

参数

setup接受两个参数。

props

props是个响应式对象。不可以使用解构语法,会丢失响应式。

该对象接受在props配置项中定义的所有内容。

export default {
    props: ['school', 'age', 'name'],
    setup(props) {
        console.log(props)
    }
}
// Proxy {school: undefined, age: undefined, name: undefined}
context

context是个普通对象。可以使用解构语法。

该对象有如下属性:

  • attrs:(对象) 接受未在props配置项定义,但是在组件传过来的属性。(等同于vue2中this.$attrs
  • emit:(函数)用于分发自定义事件,需要在emits配置项中定义该事件。(等同于vue2中this.$emit)。否则会在控制台出现警告。
  • slots(对象): 接受组件定义的插槽内容。(等同于vue2中this.$slots
  • expose:(函数)用于控制哪些内容会明确地公开暴露给组件使用者。
// 父组件
 setup() {
        let child = ref(null)
        onMounted(() => {
            console.log(child.value.n)  //undefined
            console.log(child.value.n1) //undefined
            console.log(child.value.n2) // Proxy {value: "子组件3"}
        })
        return { child }
    }
// 子组件
 setup(props, { expose }) {
        let n = ref('子组件')
        let n1 = ref('子组件1')
        let n2 = reactive({ value: '子组件3' })
        expose({ n2 })
        return { n, n1, n2 }
    }

生命周期

使用如下api需要单独引入。

在setup中通过在生命周期钩子前面加上 “on” 来访问组件的生命周期钩子。

这些函数接受一个回调函数。当钩子被组件调用时将会被执行。

destroyed/beforeDestroy 改为了unmounted/beforeUnmount。

 setup() {
         onMounted(()=>{
           // 做一些事情
         })
        return { }
   }
对应关系:
选项式 APIsetup
beforeCreate-
created-
beforeMountonBeforeMount
mountedonMounted
beforeUpdateonBeforeUpdate
updatedonUpdated
updatedonUpdated
beforeUnmountonBeforeUnmount
unmountedonUnmounted
activatedonActivated
deactivatedonDeactivated

api

使用以下api需要单独引入。

ref

let variable = ref(initVal)

创建一个响应式的数据。

  • 在setup中操作数据要使用variable.value形式。
  • 在模版中则可以直接使用。<h1>{{ variable }}</h1>
  • 如果创建的值为对象类型,在内部会使用reactive处理。
   setup() {
        let name = ref(1)
        function changeVal() {
            name.value++
        }
        return { name, changeVal }
}

在setup中使用模版引用,只会在初始渲染(mounted)之后获得赋值。

 setup() {
        let root = ref(null)
        onBeforeMount(() => {
            console.log(root.value)  // null
        })
        onMounted(() => {
            console.log(root.value) //<h3 ref="root">159</h3>
        })
        return { root }
    }

reactive

let variable = reactive(initVal)

创建对象类型的响应式数据。

  • 使用reactive创建的响应式数据无需使用variable .value来获取数据。可以直接访问。
  • reactive不能用来创建基本类型的响应式数据。控制台会提示:value cannot be made reactive:。应该用ref去创建基本类型的响应式数据。
  • reactive的响应是深层次的,可以监听到属性的添加和删除。
  • 使用reactive创建的数组类型的响应式数据,我们使用下标修改数据,在vue3中也是可以监听到的。(在vue2中这样是不能监听到的)。
 setup() {
        let re = reactive({ name: '李四', age: 123 })
        function add() {
            re.age++
            re.job = '1'
        }
        return { re, add }
    }

shallowReactive

let variable = shallowReactive(initVal)

创建对象类型响应式数据。它的响应式是浅层的,不执行嵌套对象的深层响应式转换 (暴露原始值)。

 setup() {
   let person = shallowReactive({
      name: '李四',
       age: 123,
       job: {  jb2: { slary: 20 } }
        })
        function change1() {
            person.job.jb2.slary += 1   // 页面不更新
        }
         function change() {
            person.name += '-'  // 页面更新
        }
        return { person, change1 }
    }

readonly

接受一个对象 (响应式或纯对象) 或 ref并返回原始对象的只读代理。只读代理是深层的:任何被访问的嵌套 property 也是只读的。

setup(){
let person = reactive({ name: 'lisi', jb: { jb1: {  val: 1 } } })
 function change() {  
  person.jb.jb1.val++ // Set operation on key "val" failed: target is readonly
 } 
  person = readonly(person)
 return {person,change}
 }

shallowReadonly

接受一个对象 (响应式或纯对象) 或 ref并返回原始对象的只读代理。只读代理是浅层的。

setup(){
let person = reactive({ name: 'lisi', jb: { jb1: {  val: 1 } } })
 function change() {  
  person.jb.jb1.val++ //页面更新
 } 
 function changeName() {  
  person.name+='-' //Set operation on key "name" failed: target is readonly
 } 
  person = readonly(person)
 return {person,change,changeName}
 }

computed

创建计算属性。有两种定义方式(同vue2)。

computed返回的是个ref对象。

  1. let variable = computed({ get(){},set(value) { }} ) --- 完整

    接受一个具有 getset 函数的对象,用来创建可写的 ref 对象。

  2. let variable = computed(函数) --- 简写

    相当于只有getter。 返回一个不可变的响应式 ref 对象。

watch

侦听属性。

watch(val,()=>{},[配置项])

watch 需要侦听特定的数据源,并在单独的回调函数中执行副作用。默认情况下,它也是惰性的——即回调仅在侦听源发生变化时被调用。

1.当watch监听的为ref类型定义的响应式数据时:

  • watch(ref,(newV,oldV)=>{ 处理内容 }) // 单个ref
  • watch([ref,ref],(newV,oldV)=>{ 处理内容 }) // 监听多个属性

2.当watch监听的为reactive定义的响应式数据时:

  • watch(reactive,(newV,oldV)=>{ 处理内容 })

    当监听reactive定义的对象时总是深度监听,配置deep无效。且oldV总是等于newV。

  • watch(()=>reactive.prop,(newV,oldV)=>{ 处理内容 })

    监听reactive响应式数据的某个属性时,必须使用函数返回该属性。

  • watch([()=>reactive.prop,()=>reactive.prop],(newV,oldV)=>{ 处理内容 })

    监听多个属性

watchEffect

watchEffect(()=>{})

立即执行传入的一个函数,同时响应式追踪其依赖,并在其依赖变更时重新运行该函数。

computed大体相同,但是watchEffect关注的是过程,computed关注的是结果

toRefs

let val = toRef(响应式对象)

将响应式对象转换为普通对象,其中结果对象的每个 property 都是指向原始对象相应 property 的ref。可以使用...语法,而且不会破坏响应式。

 setup() {
        let person = reactive({ name: 'lisi', age: 23 })
        let p = toRefs(person)
        return { ...p }
 }

toRef

let val = toRef(响应式对象,prop)

根据响应式对象的某个属性,创建一个 ref,ref 可以被传递。它会保持对其源 property 的响应式连接。

 setup() {
        let person = reactive({ name: 'lisi', age: 23 })
        return { u: toRef(person,'name') }
 }

toRaw

let val = toRaw(对象)

返回 reactive 或 readonly代理的原始对象。

 setup() {
        let person = reactive({ name: 'lisi', age: 23 })
        let p = toRaw(person)
        console.log(p) // {name: "lisi", age: 23}
        return { person }
  }

markRaw

let val = markRaw(对象)

标记一个对象,使其永远不会转换为 proxy。返回对象本身。

setup() {
        let val = markRaw({ name: 'wang' })
        let p = reactive(val)
        console.log(isReactive(p)) // fasle
        return {}
    }