Uvu announces that Vue3.0 has entered the candidate stage [congratulation]!! You can also try it out ahead of time by initializing a project directly from Vite. The document Beta version of Vue3.0 is also available for those interested. In addition, I will direct some Vue3 API manuals previously released by ➡️, which contains heavy and difficult responsive system API and combined API.
An overview of
Vue3.0 new features
- Composition API—- combined API, including
setup()
Etc. - Reactivity API—- Responsive system API, including
ref()
Etc. - Teleport- Built-in Teleport module
- Fragments—
template
There can be multiple DOM roots (or components) in ve2. X, there can only be one - Custom event parameters are added to the Emits component
v-model
Changes can be passed in parameters, so more than one can be usedv-model
, you can also customize the modifier to remove.sync
The modifier.createRenderer
API from@vue/runtime-core
to create custom renderers
Removed content
- removed
keyCode
Modifier, can be usedkebab-case
Name instead of (e.g.delete/.enter
) - Remove from instance
$on
.$off
和$once
methods - removedThe filter
Filters
Vue3.0 is recommendedcomputed
To implement the - Remove Inline Templates Attributes
- removed
.sync
The modifier
API references/new and deprecated apis
Bold italics represent new, deleted lines represent removed, and italics represent changes
Instance API (split from global API)
In Vue 3, the API that changes the behavior of the Vue globally is moved to the API of the instance (created with createApp). They only affect the instance. These are: mount, provide, unmount, directive (the custom directive lifecycle hook has been renamed), Component, config, mixin, use
Global API
CreateApp, h (alias for Render ()), defineComponent, defineAsyncComponent, resolveComponent (only used in render functions), resolveDirective (only used in render functions), WithDirectives (used only in render functions), createRenderer (used only in render functions), nextTick, extend, Filter, compile, Observable (replaced by Reactive), Version, SET. — Directives
options
Data
emits, data, props, computed, Methods, Watch, propsData
DOM
Template, render, el, renderError
Lifecycle hook
BeforeCreate, created, beforeMount, Mounted, beforeUpdate, updated, activated, deactivated, beforeUnmount (beforeDestroy), and unmount Ed (destroyed), errorCaptured, renderTracked, and renderTriggered
resources
Directives, components, filters
combination
Mixins, extends, provide/Inject, setup, parent
other
Name, inheritAttrs, delimiters, functional, model, comments
Instance attributes
$data, $props, $EL, $options, $parent, $root, $slots, $refs, $attrs, $children, $scopedSlots, $isServer, $Listeners
Instance methods (lifecycle incorporated here as well)
$emit, $forceUpdate, $nextTick, $set, $delete, $mount, destroy
instruction
V-text, V-html, V-show, V-if, V-else, V-else -if, V-for, V-ON, V-bind, V-model, V-slot, V-pre, V-cloak, V-once, V-is
Special attributes
Key, ref, is, slot, slot-scope, scope (these are deprecated in Vue 2.6 and above)
Built-in components
Component, transition, transition-group, keep-alive, slot, teleport
[New] Reactivity API (Reactivity API)
Basic responsive APIs
Reactive, ReadOnly, isProxy, isReactive, isReadonly, toRaw, markRaw, shallowReactive, shallowReadonly
refs
Ref, unREF, toRef, toRefs, isRef, customRef, shallowRef
Computed and watch
Computed, watchEffect, watch
[New] Composition API
Setup, onBeforeMount, onMounted, onBeforeUpdate, onUpdated, onBeforeUnmount, onUnmounted, onErrorCaptured, onRenderTracked, onRen DerTriggered, provide, inject
The following are some differences I draw from the tutorial part of the Vue2. X version. Welcome to supplement or provide suggestions for modification (because I haven’t found the Chinese version yet, so it’s just my own understanding, I have inserted the link of this part of the document in the knowledge point, you can directly view the original).
Basic usage
To create a Vue instance:
In ve2. X, an instance of Vue is created with new Vue and the DOM is mounted by passing in the EL parameter
<! -- vue2.x create instance --> var vm = new Vue({// option}) <! -- Vue2. X --> var vm = new Vue({el:'#app',
data: {a:1}
})
Copy the code
In Vue3.0, the createApp method is used to create an instance of Vue. After the instance is created, the container can be passed to the mount method for mounting
<! - Vue3.0 instance creation - > Vue. CreateApp options (/ * * /) <! -- Vue3.0 mount DOM --> vuue.createApp (/* options */).mount('#app')
Copy the code
The life cycle
The life cycle has not changed much, with some subtle differences due to the way instances are created.
It is worth noting that in Vue2. X, the two hooks that destroy the instance are beforeDestory and deStoryed, but in Vue3.0 the names of these two hooks are changed to beforeUnmount and unmounted.
Vue2. X life cycle
Vue3.0 life cycle
Provide / inject
Vue3.0 adds a description of Provide/Inject in the tutorial
Dynamic components
Both Vue2. X and Vue3.0 are still implemented by adding a special IS attribute to Vue elements
<! Components change when 'currentTabComponent' changes --> < Component V-bind :is="currentTabComponent"></component>
Copy the code
However, for parsing DOM templates, such as
-
,
<! -- Vue2. X uses the IS attribute --> <table> <tr is="blog-post-row"></tr>
</table>
Copy the code
<! -- Vue3.0 uses the v-IS instruction --> <table> <tr v-is="'blog-post-row'"></tr>
</table>
Copy the code
Custom events
Both Vue2.x and Vue3.0 still emit events via $emit(‘myEvent’) and listen for events via V-on :myEvent. The difference is that Vue3.0 provides the emits attribute in the component to define events
<! -- Vue3.0 custom events --> app.component.com ('custom-form', {
emits: ['in-focus'.'submit']})Copy the code
You can even add validation to custom events by setting emits as an object and assigning a function to the event name that takes the arguments passed to the $emit call and returns a Boolean value indicating whether the event is valid or not
<! -- Vue3.0 adds validation for custom events --> app.component.app.component.app.component.vue'custom-form', {
emits: {
// No validation
click: null,
// Validate submit event
submit: ({ email, password }) => {
if (email && password) {
return true
} else {
console.warn('Invalid submit event payload! ')
return false
}
}
},
methods: {
submitForm() {
this.$emit('submit', { email, password })
}
}
})
Copy the code
Custom componentv-model
In ve2. X, the V-Model defaults to using value as the prop name and input as the event name. For special scenarios, you can also specify the prop name and event name using the Model option (note that you still need to declare the prop in props).
<! -- Vue2.0 custom V-model --> Vue.component('base-checkbox', {
model: {
prop: 'checked',
event: 'change'
},
props: {
checked: Boolean
},
template: `
<input
type="checkbox"
v-bind:checked="checked"
v-on:change="$emit('change', $event.target.checked)"> `})Copy the code
Note that in Vue3.0, the V-Model defaults to using modelValue as the prop name and Update :modelValue as the event name that fires.
Support for passing one parameter to each V-Model so that multiple V-Models can be used simultaneously on a component
<! -- Vue3.0 defines a custom V-model and passes in an argument --> <my-component v-model:foo="bar" v-model:name="userName"></my-component>
Copy the code
You can even set custom modifiers for v-Models. The default is to accept modifiers by defining modelModifiers in props, so you can use modifiers to set the different event triggering mechanisms you want
<! -- Vue3.0 custom modifiers receive by default --> <div id="app">
<my-component v-model.capitalize="myText"></my-component>
{{ myText }}
</div>
const app = Vue.createApp({
data() {
return {
myText: ' '
}
}
})
app.component('my-component', {
props: {
modelValue: String,
modelModifiers: {
default: () => ({})
}
},
methods: {
emitValue(e) {
let value = e.target.value
if (this.modelModifiers.capitalize) {
value = value.charAt(0).toUpperCase() + value.slice(1)
}
this.$emit('update:modelValue', value)
}
},
template: `<input
type="text"
v-bind:value="modelValue"
v-on:input="emitValue">`
})
app.mount('#app')
Copy the code
Of course, for v-Models that are passed parameters, you need to configure the ARg + “Modifiers” in props to receive the V-Model Modifiers with parameters
<! -- Vue3.0 custom modifier --> < my-Component V-model :foo.capitalize="bar"></my-component>
app.component('my-component', {
props: ['foo'.'fooModifiers'],
template: `
<input type="text"
v-bind:value="foo"
v-on:input="$emit('update:foo', $event.target.value)">
`,
created() {
console.log(this.fooModifiers) // { capitalize: true}}})Copy the code
With (a mixin)
Vue. Extend ({mixins: [myMixin]}) defines a component that uses mixin objects
Var myMixin = {created:function () {
this.hello()
},
methods: {
hello: function () {
console.log('hello from mixin! 'Var Component = vue.extend ({mixins: [myMixin]}) var Component = new Component()"hello from mixin!"
Copy the code
Vue3.0 is similar to creating an instance, with vue.createApp ({mixins: [myMixin]}) defining a component that uses mixin objects
// Define a mixin object const myMixin = {created() {
this.hello()
},
methods: {
hello() {
console.log('hello from mixin! 'Const app = vue.createApp ({mixins: [myMixin]}) app.mount(const app = vue.createApp ({mixins: [myMixin]}) app.mount()'#mixins-basic') / / = >"hello from mixin!"
Copy the code
Custom instruction
The Vue2. X directive definition object contains five hooks:
bind
: called only once, the first time a directive is bound to an element. This is where you can perform one-time initialization Settings.inserted
: called when the bound element is inserted into the parent node (the parent node is guaranteed to exist, but not necessarily inserted into the document).update
: is called when the component’s VNode is updated, but may occur before its child VNodes are updated. The value of the instruction may or may not have changed. But you can ignore unnecessary template updates by comparing the values before and after the update.componentUpdated
: VNode of the component where the directive residesAnd his son VNodeCalled after all updates.unbind
: called only once, when directives are unbound from elements.
Vue3.0’s instruction object contains six hooks:
beforeMount
Called when the directive is first bound to an element. You can do it hereA one-timeInitialization Settings for.mounted
: called when the bound element is inserted into the parent node.beforeUpdate
: Updates the VNode of the componentbeforeThe call.updated
: VNode of the component where the directive residesAnd his son VNodeCalled after all updates.beforeUnmount
: called before the parent component of the bound element is unloaded. (contrast Vue2. Xnew)unmounted
: called only once, when the directive is unbound from the element and the parent component is unloaded.
In Vue3.0, components can have multiple root nodes due to fragmentation support, where using custom directives can be problematic. Custom directive objects contain hooks that are wrapped and injected into Vnode data as Vnode lifecycle hooks.
<! Call vdemo.mounted (...) {onVnodeMounted(vnode) {// call vdemo.mounted (...) }}Copy the code
When a custom directive is used in a component, these onVnodeXXX hooks are passed directly to the component as unrelated properties, and can be attached directly to the element’s lifecycle in the template like this.
<div @vnodeMounted="myHook" />
Copy the code
When a child component uses V-bind =”$attrs” on an internal element, it will also apply any custom directives on it.
Built-in transport componentTeleport
Vue3.0’s built-in < Teleport > component can transfer a template segment to another location,
<! Vue3.0 <teleport> Teleport component --> <body> <div id="app" class="demo">
<h3>Move the #content with the portal component</h3>
<div>
<teleport to="#endofbody">
<p id="content">
This should be moved to #endofbody.
</p>
</teleport>
<span>This content should be nested</span>
</div>
</div>
<div id="endofbody"></div>
</body>
Copy the code
If < Teleport > contains a Vue component, it will still be a logical child of the parent of < Teleport >, that is, even if the child is rendered in a different place, it will still be a child of the parent and will receive prop from the parent.
Using multiple transport components takes incremental logic, like this
<teleport to="#modals">
<div>A</div>
</teleport>
<teleport to="#modals"> <div>B</div> </teleport> <! <div id= <div id="modals">
<div>A</div>
<div>B</div>
</div>
Copy the code
Rendering function
The render function of Vue2. X takes createElement
The render function parameter createVNode for Vue3.0 (this name is closer to its actual meaning and returns the virtual DOM)
H is also used as an alias, which can be obtained directly from vue.h in Vue3.0
const app = Vue.createApp({})
app.component('anchored-heading', {
render() {
const { h } = Vue
return h(
'h' + this.level, // tag name
{}, // props/attributes
this.$slots.default() // array of children
)
},
props: {
level: {
type: Number,
required: true}}})Copy the code
For.passive,.capture, and.once event modifiers, the corresponding prefixes can be used with on:,
The modifier | The prefix |
---|---|
.passive |
& |
.capture |
! |
.once |
~ |
.capture.once or |
|
.once.capture |
~! |
<! -- Vue2. X prefixes modifiers --> on: {'! click': this.doThisInCapturingMode,
'~keyup': this.doThisOnce,
'~! mouseover': this.doThisOnceInCapturingMode
}
Copy the code
Vue3.0 uses object syntax
<! Vue3.0 uses object syntax for modifiers -->render() {
return Vue.h('input', {
onClick: {
handler: this.doThisInCapturingMode,
capture: true
},
onKeyUp: {
handler: this.doThisOnce,
once: true
},
onMouseOver: {
handler: this.doThisOnceInCapturingMode,
once: true,
capture: true}})}Copy the code
The plug-in
To develop the plug-in Vue3.0, you still need to expose an install method and pass in two parameters, the first being the object constructed through vue.createApp and the second optional parameter being the options passed in by the user
// plugins/i18n.js
export default {
install: (app, options) => {
// Plugin code goes here
}
}
Copy the code
Plug-in by exposing app. Config. GlobalProperties properties registered global methods
// plugins/i18n.js <! - through the app. Config. GlobalProperties global injection translate method -- -- >export default {
install: (app, options) => {
app.config.globalProperties.$translate = (key) => {
return key.split('. ')
.reduce((o, i) => { if (o) return o[i] }, i18n)
}
}
}
Copy the code
You can also provide methods or attributes to users through Inject
// plugins/i18n.js <! I18n and Options can be accessed by inject.export default {
install: (app, options) => {
app.config.globalProperties.$translate = (key) => {
return key.split('. ')
.reduce((o, i) => { if (o) return o[i] }, i18n)
}
app.provide('i18n')}} <! -- Then inject['i18n'Insert i18N into the component and access -->Copy the code
Using plug-ins is still done through the use() method, which takes two arguments, the first being the plug-in to use and the optional second being passed to the plug-in.
import { createApp } from 'vue'
import App from './App.vue'
import i18nPlugin from './plugins/i18n'
const app = createApp(App)
const i18nStrings = {
greetings: {
hi: 'Hallo! '
}
}
app.use(i18nPlugin, i18nStrings)
app.mount('#app')
Copy the code
Response principle
Responsive system
As we all know, Vue2. X is implemented via Object.defineProperty in conjunction with the subscribe/publish pattern.
When passing data to a Vue instance, Vue iterates through all the properties of the data Object and converts them all into getters/setters using Object.defineProperty, tracing dependencies when properties are accessed and modified. Each component instance corresponds to a Watcher instance, which records “touched” data properties as dependencies during component rendering. Watcher is notified when the setter for the dependency fires, causing its associated components to be re-rendered.
Vue3.0
Proxy
data
Proxy
Depend on the track
Change notification
The subscriber
set
const dinner = {
meal: 'tacos'
}
const handler = {
get(target, prop, receiver) {
track(target, prop) // Track the functionThat Changes it dependency tracingreturnReflect.get(... arguments) },set(target, key, value, receiver) {
trigger(target, key) // Trigger the functionSo it can update the final value change notificationreturnReflect.set(... arguments) } } const proxy = new Proxy(dinner, handler) console.log(proxy.meal) // intercepted! // tacosCopy the code
It is important to note that the original object is not equal to the proxy object
const obj = {}
const wrapped = new Proxy(obj, handlers)
console.log(obj === wrapped) // false
Copy the code
Reactivity Fundamentals
Declare reactive statereactive
The Reactive method takes a common object as a parameter and returns a reactive proxy of that common object (equivalent to vue.Observable () in vue2.x) to create a reactive property. Reactive transformations are “deep” in that the returned proxy object is not equal to the original object. These are the reactive properties used by the Render method during template compilation.
import { reactive } from 'vue'
// reactive state
const state = reactive({
count: 0
})
Copy the code
You can also create read-only reactive properties, also deep, and any nested properties inside the object are also read-only.
const original = reactive({ count: 0 })
const copy = readonly(original)
// mutating original will trigger watchers relying on the copy
original.count++
// mutating the copy will fail and result in a warning
copy.count++ // warning: "Set operation on key 'count' failed: target is readonly."
Copy the code
Create separate reactive propertiesrefs
The ref method takes a raw value parameter and also returns a reactive variable REF object. If it is a value of primitive type, since the value of primitive type is passed by value rather than by reference, it is like wrapping the value of primitive type into an object to ensure responsiveness, but this object contains only a unique attribute value. For reference types, reactive methods are called for deep response transformations.
import { ref } from 'vue'
const count = ref(0)
console.log(count.value) // 0
count.value++
console.log(count.value) // 1
Copy the code
When a ref is accessed in the template as an attribute returned in the render context, the inner value is automatically unwrapped, so it is no longer necessary to access xx.value as if it were a normal attribute. Note that automatic unpacking of value only occurs when nested responsive objects are accessed from native collection classes such as arrays or maps. Value is still required.
<template>
<div>
<span>{{ count }}</span>
<button @click="count ++">Increment count</button>
</div>
</template>
<script>
import { ref } from 'vue'
export default {
setup() {
const count = ref(0)
return {
count
}
}
}
</script>
Copy the code
In addition, if a new ref is assigned to an existing attribute, the old ref will be replaced
const otherCount = ref(2)
state.count = otherCount
console.log(state.count) // 2
console.log(count.value) // 1
Copy the code
To calculate
computed
methods
With a computed method, you can directly create a computed value, take a getter function as a parameter, and return a responsive object that cannot be manually modified.
const count = ref(1)
const plusOne = computed(() => count.value++)
console.log(plusOne.value) // 2
plusOne.value++ // error
Copy the code
Or you can pass in an object with getter and setter methods to create a reactive object that can be modified manually
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
Copy the code
Listening to the
watchEffect
methods
The watchEffect method listens for dependencies, runs the passed function immediately, tracks the dependencies of the function, and executes the function again as soon as the dependencies are updated.
const count = ref(0)
watchEffect(() => console.log(count.value))
// -> logs 0
setTimeout(() => {
count.value++
// -> logs 1
}, 100)
Copy the code
When watchEffect is called in a component’s Setup () or lifecycle hook, the listener is automatically linked to the component’s lifecycle and stops automatically when the component is uninstalled. Or you can stop listening by explicitly calling the return value of watchEffect.
const stop = watchEffect(() => { /* ... Vue3 // stop()Copy the code
Side Effect Invalidation clears Side effects
Sometimes the method executed in watchEffect may be asynchronous, and the function passed in by watchEffect can take an onInvalidate function as an argument to register a callback in case of a cleanup failure. It will be executed when watchEffect is re-executed or when watchEffect is terminated (or when the component is uninstalled if it is used in setup() or the lifecycle hook).
WatchEffect (onInvalidate => {const token = performAsyncOperation(id.value) onInvalidate(() => {// When id changes or listening stops // Cancel the previous asynchronous operation token.cancel()})})Copy the code
Note that setup() will be called before the component is mounted, so if you want to use DOM (or component) in watchEffect, declare watchEffect in the mounted hook
onMounted(() => {
watchEffect(() => {
// access the DOM or template refs
})
})
Copy the code
You can also pass in additional objects as parameters for watchEffect. For example, set watchEffect to be executed asynchronously or before component updates by setting Flush
// Run watchEffect(() => {/*... */ }, { flush:'sync'}) // Execute watchEffect(() => {/*... */ }, { flush:'pre'})Copy the code
The onTrack (called when tracing a dependency) and onTrigger (triggered when changing the method that triggered the watchEffect) parameters can be used to debug watchEffect behavior
watchEffect(
() => {
/* side effect */
},
{
onTrigger(e) {
debugger
}
}
)
Copy the code
Watch is lazy compared to watchEffect. It is more explicit about which state changes will trigger the listener to restart, and it can access the values before and after the monitored property changes.
Const state = reactive({count: 0}) watch(() => state.count, (count, prevCount) => {/*... Const count = ref(0) watch(count, (count, prevCount) => {/* prevCount, prevCount, prevCount, prevCount, prevCount, prevCount, prevCount, prevCount, prevCount, prevCount, prevCount, prevCount, prevCount, prevCount) * /})Copy the code
/ / listen for multiple data sources watch ([fooRef barRef], [[foo and bar], [prevFoo prevBar]) = > {/ *... * /})Copy the code
Composition API
In normal business, we often pull out reusable components such as filtering capabilities, search capabilities, business lists, and so on. But when a component composition is large, the list of logical concerns (introduced components) grows correspondingly, which can be difficult to read and understand, especially for those who didn’t write them in the first place. So we want to compose logically related code, which is what the Composition API is for.
<! We usually do this when there is no Composition API --> <! - the logic relationship between markers for the same digital -- > / / SRC/components/UserRepositories vueexport default {
components: { RepositoriesFilters, RepositoriesSortBy, RepositoriesList },
props: {
user: { type: String }
},
data () {
return {
repositories: [], // 1
filters: { ... }, // 3
searchQuery: ' ' // 2
}
},
computed: {
filteredRepositories() {... } / / 3repositoriesMatchingSearchQuery() {... }, // 2 }, watch: { user:'getUserRepositories' // 1
},
methods: {
getUserRepositories () {
// using `this.user` to fetch user repositories
}, // 2
updateFilters() {... 3}}, / /,mounted () {
this.getUserRepositories() // 1
}
}
Copy the code
Setup component parameters
Setup is a new component parameter that is used within the component and serves as an entry point to the Composition API.
The setup method takes two arguments. The first parameter is props, which is also reactive inside Setup. (Be careful not to use deconstruction assignments for props directly, which would break the reactive, but you can use toRefs for safe deconstruction.)
// MyBook.vue
import { toRefs } from 'vue'
setup(props) {
const { title } = toRefs(props)
console.log(title.value)
}
Copy the code
The second argument is context, which is a normal object (not reactive) and exposes three component properties.
// MyBook.vue
export default {
setup(props, context) {
// Attributes (Reactive Property)
console.log(context.attrs)
// Slots (Reactive Property)
console.log(context.slots)
// Emit Events (Method)
console.log(context.emit)
}
}
Copy the code
Setup is executed before the component instance is created and after props is initialized. Therefore, only props, attrs, slots, and EMIT can be accessed, not data, computed, and methods inside the component. Note that this inside setup() is not a reference to an instance of Vue.
Setup can return an object whose properties are exposed to other component options (computed properties, methods, lifecycle hooks, and so on) and component templates. It can also return a render function that uses the reactive state declared in the same scope directly:
The Composition API also contains life-cycle hook functions that look like component parameters, but are prefixed with names like onXXX, such as Mounted for onMounted, and accept a callback that is executed when the component’s hook is called.
Options API | setup In the hook |
---|---|
beforeCreate |
Don’t need |
created |
Don’t need |
beforeMount |
onBeforeMountonMounted |
mounted |
onMounted |
beforeUpdate |
onBeforeUpdate |
updated |
onUpdated |
beforeUnmount |
onBeforeUnmount |
unmounted |
onUnmounted |
errorCaptured |
onErrorCaptured |
renderTracked |
onRenderTracked |
renderTriggered |
onRenderTriggered |
Since setup runs around the beforeCreate and Created lifecycle hooks, any code that will be written in these two hooks should be written directly in Setup.
The Composition API also contains the Watch method, which takes three arguments: the first is a reactive object or function that contains a getter that we really want to listen for, the second is a callback, and the third is an optional configuration option.
There is also the computed method of the Composition API mentioned earlier that creates a computed property outside the component
So we could rewrite this as: Whenever we call the getUserRepositories method, our view will be updated with changes made in response.
// src/composables/useUserRepositories.js
import { fetchUserRepositories } from '@/api/repositories'
import { ref, onMounted, watch, toRefs } from 'vue'
export default functionUseUserRepositories (User) {// List of data repositories (create a responsive object) Const getUserRepositories = ref([] Async () => {repositories.value = await fetchUserRepositories(user.value)} onMounted(getUserRepositories) // At user Set a listener watch(User, getUserRepositories) // to return lists and methods to access in other component optionsreturn{the repositories, getUserRepositories}} / / SRC/components/UserRepositories vue / / useUserRepositorie), introduced in the component, UseRepositoryNameSearch and useRepositoryFilters import {toRefs} from'vue'
import useUserRepositories from '@/composables/useUserRepositories'
import useRepositoryNameSearch from '@/composables/useRepositoryNameSearch'
import useRepositoryFilters from '@/composables/useRepositoryFilters'
export default {
components: { RepositoriesFilters, RepositoriesSortBy, RepositoriesList },
props: {
user: { type: String }
},
setup(props) {
const { user } = toRefs(props)
const { repositories, getUserRepositories } = useUserRepositories(user)
const {
searchQuery,
repositoriesMatchingSearchQuery
} = useRepositoryNameSearch(repositories)
const {
filters,
updateFilters,
filteredRepositories
} = useRepositoryFilters(repositoriesMatchingSearchQuery)
return{// Only care about the filtered result, so we can expose it with a name like repositories: filteredRepositories, getUserRepositories, searchQuery, filters, updateFilters } } }Copy the code
You can also use provide/inject in setup, or even provide a reactive state. Note that because of one-way data flow, do not inject reactive state, but provide reactive state when provide.
import { ref, reactive } from 'vue'
// in provider
setup() {
const book = reactive({
title: 'Vue 3 Guide',
author: 'Vue Team'
})
const year = ref('2020') // You can also provide a responsive state, and try to inject it into a responsive state when provide('book', book)
provide('year', year) // If you want to provide multiple values, you can call provide} // again laterin consumer
setup() {
const book = inject('book'.'Eloquent Javasctipt') /* Optional parameter default value */ const year = inject('year')
return { book, year }
}
Copy the code
In Setup, reactive refs and template refs are unified, and to get a reference to an element or component instance within a template, declare a ref in Setup and return it. Like this we expose root in the render context and bind to the div as its ref with ref=”root”. In the virtual DOM algorithm, if the ref of the virtual node corresponds to the REF of the rendering context, then the corresponding element or component instance of the virtual node is assigned to the REF. This is performed when the virtual DOM is mounted or modified, so the template REF can only be accessed after the rendering initialization.
<template>
<div ref="root">This is a root element</div>
<div v-for="(item, i) in list" :ref="el => { divs[i] = el }">
{{ item }}
</div>
</template>
<script>
import { ref, onMounted } from 'vue'
export default {
setup() {const root = ref(null) const divs = ref([]) onMounted(() => {// After initialization DOM elements will be allocated to ref console.log(root.value) // <div>This is a root element</div>}) // Reset reference onBeforeUpdate(() => {divs.value = []})return {
root,
divs
}
}
}
</script>
Copy the code
Responsive system toolset
unref
If the argument is a ref, return its value, otherwise return the argument itself. It’s val = isRef(val), right? Val. value: syntax sugar for val.
functionUseFoo (x: number | Ref < number >) {const unwrapped = unref (x) / / unwrapped must be number type}Copy the code
toRef
ToRef can be used to create a REF for properties of a Reactive object. This REF can be passed and remains responsive. ToRef comes in handy when you want to pass a property in prop as a REF to a combinational logic function.
const state = reactive({
foo: 1,
bar: 2,
})
const fooRef = toRef(state, 'foo')
fooRef.value++
console.log(state.foo) // 2
state.foo++
console.log(fooRef.value) // 3
Copy the code
toRefs
Convert a reactive object to a normal object, each property of which is a ref, corresponding to the reactive object property. ToRefs is useful when you want to return a reactive object from a combinational logic function. This API allows the consuming component to deconstruct/extend (using… Operator), without loss of responsiveness.
isRef
Checks if a value is a ref object.
isProxy
Check whether an object is a proxy created by a reactive or Readonly method.
isReactive
Check whether an object is a reactive proxy created by Reactive. True is also returned if the agent is created by ReadOnly but is wrapped in another agent created by Reactive.
isReadonly
Checks whether an object is a read-only proxy created by ReadOnly.
Const state = reactive({foo: 1, bar: 2,}) const stateAsRefs = toRefs(state) /* stateAsRefs Ref<number>, bar: Ref<number>} */ //"Link"Stateasrefs.foo.value+ + console.log(stateasrefs.foo) // 2 stateasrefs.foo.value+ + console.log(state.foo) // 3Copy the code
Advanced responsive system API
customRef
CustomRef is used to define a ref that can explicitly control the dependency trace and trigger response. It takes a factory function with two parameters: track for trace and trigger for response. And returns an object with get and set attributes. This is a chestnut using a custom ref to implement a v-model with stabilization
<input v-model="text" />
function useDebouncedRef(value, delay = 200) {
let timeout
return customRef((track, trigger) => {
return {
get() {
track()
return value
},
set(newValue) {
clearTimeout(timeout)
timeout = setTimeout(() => {
value = newValue
trigger()
}, delay)
},
}
})
}
export default {
setup() {
return {
text: useDebouncedRef('hello'),}}}Copy the code
markRaw
This function explicitly marks an object as “never converted to a responsive proxy” and returns the object itself.
shallowReactive
Create shallow, responsive proxies for private (layer 1) properties of an object, not deep, recursive, responsive proxies for “properties of properties,” but just leave them as they are.
shallowReadonly
Create shallow read-only responsive proxies for an object’s own (level 1) properties, as well as deep, recursive proxies that are not read-only.
shallowRef
A ref is created and its.value changes are tracked, but reactive proxy transformations are not performed on the changed.value.
toRaw
Returns ordinary objects that are transformed into reactive proxies by reactive or Readonly methods. This is a restore method that can be used for temporary reads without access being proxied/tracked and without triggering changes on writes. Holding a reference to the original object is not recommended. Use with caution.
Plus, a couple of things. First, Vue3.0 is refactored in TypeScript, and TS’s type checking greatly reduces the chance of introducing unexpected errors, reducing maintenance costs.
Vue3.0 optimizes the algorithm of virtual DOM. When detecting all nodes, a template can be split into nested blocks separated by these structural instructions. For template instructions that do not dynamically change the node structure (such as using V-IF or V-for), the node structure of this piece is static. The code it generates is pushed out of the rendering function. You don’t have to re-create these objects every time you need to re-render them, which also increases memory usage and reduces garbage collection. At the element level, the compiler generates an optimization flag for dynamically bound elements based on the type of update that needs to be performed, which is picked up at run time and takes a faster path.
Vue3.0 was also moved to the module.exports property through most global apis and helpers. Module Bundler statically analyzes module dependencies and removes code associated with unused module.exports properties. It also generates tree jitter friendly code and imports helper programs for a feature only after it is actually used in the template.
Despite the new features, the compressed size of Vue3.0 is half that of VUe2.x!
These are the differences from the tutorial. The most important ones are the Composition API and Reactivity, which I find the most difficult. In addition, the document of Vue3.0 is still under development, and there may be some changes in the future. Please refer to the document as the standard. I haven’t started the development directly, so I don’t put forward too many personal opinions, just as a comparison with VUe2.x.