vue3.0新特性初体验(一)

2020-09-08 17:51:33 浏览数 (1)

作者:炮哥 作者:炮哥

自从尤大的3.0横空出世以来,备受关注。感觉写法越来越像React,不过尤大也说了,其中一部分是受到了React hooks的思想影响。本系列文章将先带大家了解vue3.0, 会用vue3.0,以及最后了解vue3.0源码。

先带大家了解下vue3.0的新特性玩法:(至于怎样创建vue3.0项目这里不再做更多的阐述,想了解的可以一移步官网。):

setup

setup是新的组件选项。它充当在组件内部使用入口点。

  • 调用时间

setup创建组件实例时,在初始组件解析后立即调用。在生命周期方面,它在beforeCreate之后, created之前被调用(2.x)。

  • 模板使用

如果setup返回一个对象,则该对象的属式将合并到组件模板的渲染上下文中:

代码语言:txt复制
<template>
  <div>{{ count }} {{ object.foo }}</div>
</template>

<script>
import { ref, reactive } from 'vue'

export default {
  setup() {
    const count = ref(0)
    const object = reactive({ foo: 'bar' })

    // expose to template
    return {
      count,
      object
    }
  }
}
</script>

请注意,setup 在模板中访问时,从ref返回的引用将自动解包,因此模板中使用不需要.value。在setup中访问必须需要.value

  • Render/ JSX用法

setup 还可以返回一个render函数:

代码语言:txt复制
import { h, ref, reactive } from 'vue'

export default {
  setup() {
    const count = ref(0)
    const object = reactive({ foo: 'bar' })

    return () => h('div', [
      count.value,
      object.foo
    ])
  }
}

接收 props 数据

  • 第一个接收的是props数据:export default { props: { name: String }, setup(props) { console.log(props.name) } }props数据可以用 watch 方法来监听:
代码语言:txt复制
export default {
  props: {
    name: String
  },
  setup(props) {
    watch(() => {
      console.log(`name is: `   props.name)
    })
  }
}

在开发过程中,props对象不可更改(如果用户代码尝试对其进行更改,则会发出警告).

  • 第二个参数提供了一个上下文对象,该对象公开了先前在2.x API中使用this公开的属式:
代码语言:txt复制
// 2.0 中 this.$emit()
const MyComponent = {
  setup(props, context) {
    console.log(context)
    context.attrs
    context.slots
    context.emit
    context.ref
  }
}

context中的对象使用方式和2.0中的保持一致:

attrs并且slots是内部组件实例上对应值的代理。这样可以确保即使在更新后它们也始终显示最新值,以便我们可以对它们进行结构解析而不必担心访问陈旧的引用:

代码语言:txt复制
const MyComponent = {
  setup(props, { attrs }) {
    // a function that may get called at a later stage
    function onClick() {
      console.log(attrs.foo) // guaranteed to be the latest reference
    }
  }
}
  • this用法

this里面没有setup()。由于setup()是在解析2.x选项之前调用的,因此this内部setup()(如果可用)的行为将与this其他2.x选项完全不同。避免this进入的另一个原因setup()是对于初学者来说非常常见的陷阱:

代码语言:txt复制
setup() {
  function onClick() {
    this // not the `this` you'd expect!
  }
}

reactive

取得一个对象并返回原始对象的响应式代理。这等效于2.x的Vue.observable()

代码语言:txt复制
const obj = reactive({ count: 0 })

响应式转换是“深度”的:它影响所有嵌套的属式。在基于ES2015代理的实现中,返回的代理不等于原始对象。建议仅与响应式代理一起使用,并避免依赖原始对象。

ref

接受一个值并返回一个响应式且可变的ref对象。ref对象具有.value指向内部值的单个属式。

代码语言:txt复制
const count = ref(0)
console.log(count.value) // 0

count.value  
console.log(count.value) // 1

如果将一个对象分配为ref的值,则该reactive方法会使该对象具有高度的响应式。

  • 模板访问

当ref作为渲染上下文(从中返回的对象setup())的属式返回并在模板中进行访问时,它会自动展开为内部值。无需.value在模板中附加:

代码语言:txt复制
<template>
  <div>{{ count }}</div>
</template>

<script>
export default {
  setup() {
    return {
      count: ref(0)
    }
  }
}
</script>

响应式对象中的访问

当ref被访问或作为响应对象的属式进行更改时,它会自动展开为内部值,因此其行为类似于普通属式:

代码语言:txt复制
const count = ref(0)
const state = reactive({
  count
})

console.log(state.count) // 0

state.count = 1
console.log(count.value) // 1
请注意,ref内部值可以被覆盖/替换:

const otherCount = ref(2)

state.count = otherCount
console.log(state.count) // 2
console.log(count.value) // 1

isRef

检查值是否是ref的引用对象。

代码语言:txt复制
const unwrapped = isRef(foo) ? foo.value : foo

toRefs

响应对象转换为普通对象,其中结果对象上的每个属式都是指向原始对象中相应属式的ref;常用于reactive解构/扩展时使用

代码语言:txt复制
const state = reactive({
  foo: 1,
  bar: 2
})

const stateAsRefs = toRefs(state)
/*
Type of stateAsRefs:

{
  foo: Ref<number>,
  bar: Ref<number>
}
*/

// The ref and the original property is "linked"
state.foo  
console.log(stateAsRefs.foo) // 2

stateAsRefs.foo.value  
console.log(state.foo) // 3

toRefs 从组合函数返回反应对象时,此函数很有用,以便使用组件可以对返回的对象进行解构/扩展而不会失去响应式:

代码语言:txt复制
function useFeatureX() {
  const state = reactive({
    foo: 1,
    bar: 2
  })

  // logic operating on state

  // convert to refs when returning
  return toRefs(state)
}

export default {
  setup() {
    // can destructure without losing reactivity
    const { foo, bar } = useFeatureX()

    return {
      foo,
      bar
    }
  }
}computed使用

const count = ref(1)

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

console.log(plusOne.value) // 2

plusOne.value // error

代码语言:txt复制
  
或者,它可以使用具有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

代码语言:txt复制
## readonly
  
接受一个对象(响应式或普通)或ref并返回对原始对象的只读(和响应式)代理。可以理解为`代理`。

const original = reactive({ count: 0 })

const copy = readonly(original)

watch(() => {

// works for reactivity tracking

console.log(copy.count)

})

// mutating original will trigger watchers relying on the copy

original.count

// mutating the copy will fail and result in a warning

copy.count // warning!

0 人点赞