Vue 3.0 中文手册 (上)


Vue 3 安装

天才第一步首先你得安装Vue3

方案一:

  • 克隆源代码 https://github.com/vuejs/vue-next

找到package.json不难看出在scripts中各种启动命令项,同时也发现到作者使用rollup进行构建项目。 下载依赖npm install后,执行npm run dev编译不出意外会生成一个目录packages/vue/dist/vue.global.js文件,这就是vue3核心文件。 启动项目npm run serve不难发现启动一个端口为localhost:5000的页面。再跟目录中建立一个文件夹test里面创建两个文件分别:index.html 、index.js

  • index.html




  
  
  
  Vue.js


  
  • index.js

const {reactive, computed} = Vue;

const App = {
  template: `
    
    
{{state.message}}, double is: {{state.double}}
`, setup() { const state = reactive({ message: 10, double: computed(() => state.message * 3) }) function increment() { state.message++ } return { state, increment } } } Vue.createApp(App).mount("#app");

进入html页面中不难发现成功运行一个vue3小demo

方案二:

安装  cli

npm install -g @vue/cli
// 如果安装失败可以切换至淘宝镜像
cnpm install -g @vue/cli

检测 cli版本

vue -V
// @vue/cli 4.3.1

初始化项目

vue create vue-next

升级为Vue 3

cd vue-next-test
vue add vue-next

启动

npm run serve

安装并且启动完成我们来看看

Vue 3 生命周期

前言

Vue2Vue3中的生命周期钩子非常相似–我们仍然可以访问相同的钩子,并且我们仍然希望将它们用于相同的用例。

但是,随着Composition API的引入,我们访问这些钩子的方式已经改变。

到本文结束时,您将了解在Vue3中使用生命周期钩子的新方法,并开始编写更好的代码。

我们走吧!

Composition API : https://learnvue.co/2019/12/a-first-look-at-vue3-a-vue-composition-api-tutorial/

什么是成分API

如果您还不了解,则Vue3 Composition API带有setup()方法。此方法封装了我们的大多数组件代码,并处理了反应性,生命周期钩子等。

简而言之,Composition API使我们能够更好地将代码组织为更多的模块化功能,而不是根据属性的类型(methods, computed, data)进行分离。

Vue 3.0 中文手册 (上)_第1张图片

在旧的beforeCreate钩子之后和创建的钩子之前立即调用setup方法。因此,我们不再需要这两个钩子,我们可以简单地将本应有的代码放在setup()方法中。

添加我们的生命周期钩子

与Vue3中的大多数功能一样,生命周期钩子是我们必须导入到项目中的东西。这是为了帮助使项目尽可能轻巧。

我们导入生命周期钩子的方式是这样的。

import { onMounted, onUpdated, onUnmounted } from'vue'

beforeCreatecreated之外,我们可以在设置方法中访问9个旧的生命周期钩子

  • onBeforeMount –在安装开始之前调用

  • onMounted –在安装组件时调用

  • onBeforeUpdate –在反应性数据更改时以及重新呈现之前调用

  • onUpdated –重新渲染后调用

  • onBeforeUnmount –在销毁Vue实例之前调用

  • onUnmount –在实例被销毁后调用

  • onActivated –当激活kept-alive组件时调用

  • onDeactivated –当kept-alive组件被停用时调用

  • onErrorCaptured –从子组件捕获错误时调用

当我们导入它们并在我们的代码中访问它们时,它将看起来像这样。

import { onBeforeMount, onMounted, onBeforeUpdate, onUpdated, onBeforeUnmount, onUnmounted, onActivated, onDeactivated, onErrorCaptured } from'vue'

exportdefault {
  setup() {
    onBeforeMount(() => {
      // ... 
    })
    onMounted(() => {
      // ... 
    })
    onBeforeUpdate(() => {
      // ... 
    })
    onUpdated(() => {
      // ... 
    })
    onBeforeUnmount(() => {
      // ... 
    })
    onUnmounted(() => {
      // ... 
    })
    onActivated(() => {
      // ... 
    })
    onDeactivated(() => {
      // ... 
    })
    onErrorCaptured(() => {
      // ... 
    })
  }
}

从Vue2转换为Vue3

方便的Vue2到Vue3生命周期映射直接来自Vue3 Composition API文档,我认为这是了解事物将如何变化以及如何使用它们的最有用的方法之一。

  • beforeCreate -> use setup()

  • created -> use setup()

  • beforeMount -> onBeforeMount

  • mounted -> onMounted

  • beforeUpdate -> onBeforeUpdate

  • updated -> onUpdated

  • beforeDestroy -> onBeforeUnmount

  • destroyed -> onUnmounted

  • errorCaptured -> onErrorCaptured

新增加的钩子

我们还可以在Vue3中使用两个全新的钩子来进行调试。他们是:

  1. onRenderTracked

  2. onRenderTriggered

这两个事件都带有一个DebuggerEvent,它使我们能够知道是什么导致了Vue实例中的重新渲染。

exportdefault {
  onRenderTriggered(e) {
    debugger
    // 检查哪个依赖项导致组件重新呈现
  }
}

总结

如果您已经有Vue的经验,那么这将是一个非常容易的切换。只需导入钩子并将它们包括在设置方法中即可。

我希望这可以帮助您更多地了解Vue3中的更改以及如何在项目中实现它们。

Composition API

前言

随着Vue3 Alpha的发布,许多开发人员都在尝试新的变化——最大的变化是 Composition API

setup

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

调用时间

setup创建组件实例时,在初始道具解析后立即调用。在生命周期方面,它在beforeCreate挂载之前被调用。

模板使用

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




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

渲染功能/ JSX的用法

setup 还可以返回一个render函数,该函数可以直接使用在同一作用域中声明的反应状态:

import { h, ref, reactive } from'vue'

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

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

参数

该函数将接收到的props作为其第一个参数:

exportdefault {
  props: {
    name: String
  },
  setup(props) {
    console.log(props.name)
  }
}

请注意,此props对象是反应性的-即,当传入新的道具时会更新该对象,使用watchEffect或可以观察到并做出反应watch

exportdefault {
  props: {
    name: String
  },
  setup(props) {
    watchEffect(() => {
      console.log(`name is: ` + props.name)
    })
  }
}

但是,请勿破坏props对象,因为它会失去反应性:

exportdefault {
  props: {
    name: String
  },
  setup({ name }) {
    watchEffect(() => {
      console.log(`name is: ` + name) 
    })
  }
}

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

第二个参数提供了一个上下文对象,该对象公开了先前this在2.x API中公开的属性的选择性列表:

const MyComponent = {
  setup(props, context) {
    context.attrs
    context.slots
    context.emit
  }
}

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

const MyComponent = {
  setup(props, { attrs }) {
    // 在以后的阶段可能会被调用的函数
    function onClick() {
      console.log(attrs.foo) // 保证是最新的参考
    }
  }
}

Reactivity

reactive

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

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

Typing

function reactive(raw: T): T

ref

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

const count = ref(0)
console.log(count.value) // 0

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

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

Access in Templates

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




Access in Reactive Objects

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

const count = ref(0)
const state = reactive({
  count
})

console.log(state.count) // 0

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

请注意,如果将新的引用分配给链接到现有引用的属性,它将替换旧的引用:

const otherCount = ref(2)

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

请注意,仅当ref嵌套嵌套在react时才发生Object。从ref Array或本机集合类型(如)访问ref时,不会执行解包Map

const arr = reactive([ref(0)])
// 这里需要value
console.log(arr[0].value)

const map = reactive(newMap([['foo', ref(0)]]))
// 这里需要value
console.log(map.get('foo').value)

Typing

interface Ref {
  value: T
}

function ref(value: T): Ref

有时我们可能需要为ref的内部值指定复杂类型。我们可以通过在调用ref以覆盖默认推断时传递泛型参数来简洁地实现此目的:

const foo = ref('foo') // foo's type: Ref

foo.value = 123// ok!

computed

使用getter函数,并为getter返回的值返回一个不变的反应性ref对象。

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

console.log(plusOne.value) // 2

plusOne.value++ // error

或者,它可以使用具有getset功能的对象来创建可写的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

Typing

// read-only
function computed(getter: () => T): Readonly>>

// writable
function computed(options: {
  get: () => T
  set: (value: T) => void
}): Ref

readonly

取得一个对象(反应性或普通)或ref,并返回一个只读代理到原始对象。只读代理很深:访问的任何嵌套属性也将是只读的。

const original = reactive({ count: 0 })

const copy = readonly(original)

watchEffect(() => {
  // 用于反应性跟踪
  console.log(copy.count)
})

// 对原版本进行变异将会引发观察者对拷贝的依赖
original.count++

// 更改副本将失败并导致警告
copy.count++ // warning!

watchEffect

在反应性地跟踪其依赖关系时立即运行一个函数,并在依赖关系发生变化时重新运行它。

const count = ref(0)

watchEffect(() =>console.log(count.value))
// -> logs 0

setTimeout(() => {
  count.value++
  // -> logs 1
}, 100)

Stopping the Watcher

watchEffect在一个组件的调用setup()功能或生命周期挂钩,观察者链接到组件的生命周期,当组件卸载将自动停止。

在其他情况下,它返回停止句柄,可以调用该句柄以显式停止观察程序:

const stop = watchEffect(() => {
  /* ... */
})

// later
stop()

Side Effect Invalidation

有时,受监视的效果函数会执行异步副作用,当无效该副作用时,需要清理该异步副作用(即,在完成效果之前更改状态)。效果函数接收onInvalidate可用于注册无效回调的函数。在以下情况下调用无效回调:

  • 效果将重新运行

  • 观察者停止(例如,如果watchEffect在内部setup()或生命周期挂钩中使用该组件,则该组件将被卸下)

watchEffect(onInvalidate => {
  const token = performAsyncOperation(id.value)
  onInvalidate(() => {
    // id has changed or watcher is stopped.
    // invalidate previously pending async operation
    token.cancel()
  })
})

我们正在通过传递的函数注册无效回调,而不是从回调(如React useEffect)返回无效回调,因为返回值对于异步错误处理很重要。在执行数据提取时,效果函数通常是异步函数:

const data = ref(null)
watchEffect(async () => {
  data.value = await fetchData(props.id)
})

异步函数隐式返回Promise,但是在Promise解析之前,必须立即注册清除函数。此外,Vue依靠返回的Promise来自动处理Promise链中的潜在错误。

Effect Flush Timing

Vue的反应系统缓冲无效的效果,并异步刷新它们,以避免在同一“标记”中发生许多状态突变时不必要的重复调用。在内部,组件的更新功能也是受监视的效果。当用户效果排队时,总是在所有组件更新效果之后调用它:




在此示例中:

  • 该计数将在初始运行时同步记录。

  • count发生突变时,回调将被调用**后,**组件已更新。

请注意,第一次运行是在安装组件之前执行的。因此,如果您希望以监视的效果访问DOM(或模板引用),请在安装的挂钩中进行操作:

onMounted(() => {
  watchEffect(() => {
    // access the DOM or template refs
  })
})

如果需要同步运行观察者效果或在组件更新之前重新运行,我们可以将附加的options对象与flush选项一起传递(默认值为'post'):

// fire synchronously
watchEffect(
  () => {
    /* ... */
  },
  {
    flush: 'sync'
  }
)

// fire before component updates
watchEffect(
  () => {
    /* ... */
  },
  {
    flush: 'pre'
  }
)

Watcher Debugging

onTrackonTrigger选项可以用来调试观察者的行为。

  • onTrack 当将反应性属性或ref跟踪为依赖项时将被调用

  • onTrigger 当监视者回调由依赖项的突变触发时将被调用

这两个回调都将接收到一个调试器事件,该事件包含有关所依赖项的信息。建议debugger在这些回调中放置一条语句以交互方式检查依赖关系:

watchEffect(
  () => {
    /* side effect */
  },
  {
    onTrigger(e) {
      debugger
    }
  }
)

onTrack并且onTrigger仅适用于开发模式。

Typing

function watchEffect(
  effect: (onInvalidate: InvalidateCbRegistrator) => void,
  options?: WatchEffectOptions
): StopHandle

interface WatchEffectOptions {
  flush?: 'pre' | 'post' | 'sync'
  onTrack?: (event: DebuggerEvent) =>void
  onTrigger?: (event: DebuggerEvent) =>void
}

interface DebuggerEvent {
  effect: ReactiveEffect
  target: any
  type: OperationTypes
  key: string | symbol | undefined
}

type InvalidateCbRegistrator = (invalidate: () => void) =>void

type StopHandle = () =>void

Vue 3.0 中文手册 (上)_第2张图片

你可能感兴趣的:(Vue 3.0 中文手册 (上))