The early provided for everyone to learn, now you can move to the Chinese document

V3.cn.vuejs.org Modified at 2020/9/21- The official version of vue3 was released on 2020/9/18

The global configuration API changes of Vue2 and Vue3 are different

createApp

  • Vue2. X creates an instance and mounts it to the DOM

    import Vue from "vue";
    import App from './App.vue'
    
    new Vue({
      render: (h) => h(App)
    }).$mount("#app");
    Copy the code
  • Vue3 new API ===>createApp source address create instance

    CreateApp generates an app instance that has a globally configurable context

    import { createApp } from 'vue'
    import App from './App.vue'
    
    createApp(App).mount('#app')
    Copy the code

What does createApp do

  • The ensureRenderer method retrodetermines the pastAdd patchClass +patchStyle and other DOM related methods
    • EnsureRenderer goes all the way back to createRenderer and baseCreateRenderer, a method that involves the creation and updating DIFF algorithm of the virtual DOM
  • Then it’s time to check if it’s mounted to the DOM
  • Methods on app objects: config, use, mixin, Component, directive, mount, unmount, provide/inject

component

  • Vue2. X [Register or get the global component. Registration also automatically sets the component name with the given ID.]

    Vue.component('my-component', {/*... Var MyComponent = Vue.com ('my-component') var MyComponent = Vue.com ('my-component')Copy the code
  • Vue3 [Register or get global components. Registration also automatically sets the name of the component with the given name component] global components

    The basic writing method of VUe2 is the same

    Import {createApp} from 'vue' const app = createApp({}) import {createApp} from 'vue' const app = createApp({}) import {createApp} from 'vue' const app = createApp({}) */}) // Get registered component(always return constructor) const MyComponent = app.component.ponent ('my-component', {})Copy the code

configThe app = createApp (app).

devtools

Configure whether vue-devtools is allowed to examine code. The development version defaults to true and the production version defaults to false. The production version is set to true to enable checking.

- Vue.config.devtools = true
+ app.config.devtools = true    
Copy the code

errorHandler

- vue.config. errorHandler = function (err, vm, info) {// Handle error // 'info' is a Vue specific error message, } + app.config.errorHandler = (err, vm, Info) => {// handle error // 'info' is Vue specific error information, such as the lifecycle hook where the error is located // Errors can be found here}Copy the code

Specifies a handler that does not catch errors during rendering and viewing of the component. When this handler is called, it gets an error message and a Vue instance.

Error tracking services Sentry and Bugsnag both provide official support through this option.

warnHandler

-vue. Config. warnHandler = function(MSG, vm, trace) {// 'trace' is a trace of component} + app.config.warnHandler = function(MSG, vm, trace) Vm, trace) {// 'trace' is a component inheritance trace}Copy the code

Give a custom handler to Vue’s runtime warnings. Note that this only works in the developer environment and is ignored in production.

globalProperties[New attributes]

app.config.globalProperties.foo = 'bar'

app.component('child-component', {
  mounted() {
    console.log(this.foo) // 'bar'
  }
})
Copy the code

Add global properties that can be accessed in any component instance within the program. Component properties take precedence when there are key conflicts

Replaces Vue2. X with vue. prototype property on the prototype

// Vue2.x
Vue.prototype.$http = () => {}

// Vue3
const app = Vue.createApp({})
app.config.globalProperties.$http = () => {}
Copy the code

isCustomElement[New attributes]

  • Replace Vue2. X ignoredElements
- Vue. Config. IgnoredElements = [/ / with a ` RegExp ` ignore all "ion -" the beginning of the element / / only in 2.5 + support / ^ ion - /] / / some components begin with 'ion -' + will be resolved as a custom component app.config.isCustomElement = tag => tag.startsWith('ion-')Copy the code

Specify a method to identify custom components defined outside of Vue (for example, using the Web Component API). If the component meets this condition, it does not need to be registered locally or globally, and Vue does not throw warnings about Unknown Custom Elements

Note that there is no need to match all native HTML and SVG tags in this function – the Vue parser does this check automatically

optionMergeStrategies

const app = Vue.createApp({
  mounted() {
    console.log(this.$options.hello)
  }
})

app.config.optionMergeStrategies.hello = (parent, child, vm) => {
  return `Hello, ${child}`
}

app.mixin({
  hello: 'Vue'
})

// 'Hello, Vue
Copy the code

Defines the merge policy for custom options.

The merge strategy accepts parental and ∗∗ sub-instances ∗options and ** ∗ sub-instances **options and ∗∗ sub-instances ∗options as the first and second parameters, respectively. The context Vue instance is passed as the third parameter

[Custom option combination Strategy]mixin
const app = Vue.createApp({ custom: 'hello! ' }) app.config.optionMergeStrategies.custom = (toVal, fromVal) => { console.log(fromVal, toVal) // => "goodbye!" , undefined // => "hello!" , "goodbye!" return fromVal || toVal } app.mixin({ custom: 'goodbye! ', created() { console.log(this.$options.custom) // => "hello!" }})Copy the code
  • OptionMergeStrategies get the mixin of the child instance without the parent instance [custom first changes from undefined to Goodbye –> print “Goodbye!”, undefined]
  • [custom second from goodbye to hello!– > prints “hello”, “Goodbye!”]
  • Finally in print app. Config. OptionMergeStrategies. The custom return the $options of parent instance

In any case this. Options. custom will return the return value of the merge policy OptionMergeStrategies Merges $options changes using the options of the parent component and returns the desired value by doing calculations and so on

performance

- Vue.config.performance=true;
+ app.config.performance=true;
Copy the code

Set to true to enable performance tracking for component initialization, compilation, rendering, and patching in the browser developer’s Performance/timeline panel. Only works in development mode and on browsers that support the Performance. Mark API.

directiveTutorial document

Register or get global directives.

Import {createApp} from 'vue' const app = createApp({}) // App. directive('my-directive', // Call beforeMount(el, binding, vnode) {}. // Call Mounted (el, binding, vnode) {} when mounting the parent of a binding element. Call beforeUpdate(el, binding, VNode, prevNode) {} before updating the VNode containing the component, call updated(el, binding, prevNode) after updating the VNode of the component and its children. Vnode, prevNode) {}, beforeUnmount(el, binding, vnode) {}, beforeUnmount(el, binding, vnode) {}, call unmounted(el, binding, vnode) before unmounting the parent of a binding element. Vnode) {}}) // Register (directive function) app.directive('my-directive', (el, binding, vnode, PrevNode) => {// Mounted and 'updated'}) // getter, returns the registered directive const myDirective = app.directive('my-directive')Copy the code

  • el

    The element to which the directive is bound. This can be used to manipulate the DOM directly.

  • Binding [object containing the following attributes]

    • Instance: An instance of a component that uses a directive

    • Value: specifies the binding value of the directive. For example, v-my-directive=”1 + 1″, the binding value is 2

    • OldValue: The previous value of the directive binding, available only in beforeUpdate and updated hooks. Available regardless of whether the value changes

    • Arg: Optional parameter passed to the instruction. For example, in v-my-directive:foo, the parameter is “foo”.

    • Modifiers: An object that contains modifiers. For example, in v-my-directive.foo.bar, the modifier object is {foo: true, bar: true}.

    • Dir: an object passed as a parameter when registering instructions; As an example, look at the following instructions

      app.directive('focus', {
        mounted(el) {
          el.focus()
        }
      })
      Copy the code

      Dir is the object below

      {
        mounted(el) {
          el.focus()
        }
      }
      Copy the code
  • vnode

    Virtual nodes generated by compilation

  • prevNode

    The previous virtual node is only available in beforeUpdate and updated hooks

    Tips: All parameters except el should be read-only. Do not change them. If you need to share data between hooks, it is recommended to do so through the element’s dataset

Mixin [basic Vue2. X consistency]

  • OptionMergeStrategies impact, see above

Globally register a mixin that affects all Vue instances created after registration. Plug-in authors can use interfuse to inject custom behavior into components. Not recommended for use in application code.

Mount 【 akin to Vue2. X 】

Mount the root component of the application instance on the supplied DOM element

Import {createApp} from 'vue' const app = createApp({}) // Do some preparation app.mount('#my-app')Copy the code

Provide /inject [Vue2. X consistent]

This option is used with Inject, which allows an ancestor component to act as a dependency injector for all its descendants, no matter how deep the component hierarchy is, as long as they are in the same parent chain

The provide option should be an object or a function that returns an object. This object contains properties that can be injected into its descendants. You can use ES2015 Symbols as keys in this object, but this only works if Symbol and reflect.ownKeys are natively supported.

If you have a component in which both can only be called in setup() of the currently active component instance, see the dependency injection section for details

import { createApp } from 'vue'

const app = createApp({
  provide: {
    user: 'John Doe'
  }
})

app.component('user-card', {
  inject: ['user'],
  template: `
    <div>
      {{ user }}
    </div>
  `
})
Copy the code

Unmount [New attribute]

Unload the root component of the application instance on the supplied DOM element

Import {createApp} from 'vue' const app = createApp({}) // Make the necessary preparations app.mount('#my-app') // The app will be unmounted 5 seconds after it is mounted setTimeout(() => app.unmount('#my-app'), 5000)Copy the code

Use [Vue2. X consistent]

Install vue.js plug-in. If the plug-in is an object, the install method must be provided. If the plug-in were a function, it would be used as the install method. When the install method is called, Vue is passed in as an argument.

When the install method is called multiple times by the same plug-in, the plug-in will only be installed once.

setup

The setup function is a new component option. As an entry point for using the Composition API within components

  • Pay attention tosetupThe returned ref is automatically untangled in the template without writing.valuesetupInternal needs.value

Call time

  • Create the component instance, initialize props, and then call the setup function. From a lifecycle hook perspective, it is called before the beforeCreate hook

  • If Setup returns an object, the properties of the object will be incorporated into the rendering context of the component template

parameter

  • propsAs its first parameter

Note that the props object is reactive. WatchEffect or Watch watches and responds to updates to the props

Do not deconstruct the props object; that will make it unresponsive

export default {
  props: {
    name: String,
  },
  setup(props) {
    console.log(props.name)
     watchEffect(() => {
      console.log(`name is: ` + props.name)
    })
  },
}
Copy the code
  • The second argument provides a context object (from the original 2.x this selectively exposes some properties (attrs/emit/slots)).

    Attrs and slots are proxies for the corresponding item on the internal component instance, ensuring that the value remains up to date even after updates. So you can deconstruct it without worrying about accessing expired values later

    Why props as the first parameter?

    • Components usepropsMore scenarios, sometimes even just useprops
    • willpropsAs the first argument, it is possible to make TypeScript pairspropsType inference alone is not confused with other attributes in the context. It also makessetuprenderBe consistent with the signatures of other functional components that use TSX

    This is not available in setup(). Since setup() is called before parsing the 2.x option, this in setup() will be completely different from this in the 2.x option. Using this in both the setup() and 2.x options causes confusion

    setup(props, { attrs }) {
        // A signature that can be called later
        function onClick() {
          console.log(attrs.foo) // Must be the latest reference, no loss of responsiveness}}Copy the code

Responsive system API

reactive

Desc: reactive proxy that receives a common object and returns the common object [equivalent to vue.Observable () in 2.x]

  • ssss

    Tips: The Proxy object is a Proxy for the target object, and any operation on the target object (instantiation, adding/deleting/modifying properties, and so on) must go through this Proxy. So we can block and filter or modify all operations from the outside world

Reactive transformations are “deep” : they affect all nested properties inside the object. The Proxy implementation based on ES2015 does not return a Proxy object equal to the original object. It is recommended to use only proxy objects instead of relying on primitive objects

The API of Reactive class mainly provides the ability to process complex types of data into responsive data. In fact, this complex type is in object array map set WeakMap Weakset.

Because it is a composite function, a reference to the returned object must always be kept to remain responsive, such as const {x, y} = useMousePosition() or return {… useMousePosition() }

function useMousePosition() {
    const pos = reactive({
        x: 0.y: 0,})return pos
}
Copy the code

The toRefs API is used to provide a solution to this constraint by converting each property of a responsive object to the corresponding REF.

 function useMousePosition() {
    const pos = reactive({
        x: 0.y: 0,})return toRefs(pos)
}

// x & y is now in ref form!
const { x, y } = useMousePosition()
Copy the code

ref

Accepts a parameter value and returns a reactive and mutable REF object. The ref object has a single.value attribute that points to an internal value

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

If an object is passed to a REF, the reactive methods are called for the deep response transformation

trap

  • Setup return is automatically unwrapped.

  • Value is also unnested automatically when the property of a ref that is a Reactive object is accessed or modified

    const count = ref(0)
    /* As an object attribute of reactive ---- unpack */
    const state = reactive({
      count,
    })
    /* No. Value */
    console.log(state.count) / / 0
    
    /* Change the value of reactive */
    state.count = 1
    /* changes the value of ref */
    console.log(count.value) / / 1
    Copy the code

    Note that if a new ref is assigned to an existing ref, the old ref is replaced

    /* Create a new ref*/
    const otherCount = ref(2)
    
    /* The old ref assigned to reactive will be replaced */
    state.count = otherCount
    /* Changing reactive changes otherCount*/
    console.log(state.count) / / 2
    /* Change reactive count is not changed */
    console.log(count.value) / / 1
    Copy the code
  • A REF is unnested only when nested in a Reactive Object. From the original collection classes such as Array or Map when accessing a ref, don’t automatically solution set of the free data type is Object solution set, Array Map set weakmap weakset collection classes when accessing a ref, does not automatically unlock 】

    const arr = reactive([ref(0)])
    // We need.value
    console.log(arr[0].value)
    
    const map = reactive(new Map([['foo', ref(0)]]))
    // We need.value
    console.log(map.get('foo').value)
    Copy the code

Mentally burdenedref vs reactive

  • In normal JavaScriptDeclare the underlying type variablewithObject variablesIs used differentlyrefreactive
  • All over the placereactiveThen remember to use it when the composite function returns a reactive objecttoRefs. This takes some of the mental weight off ref

readonly

Passing in an object (reactive or plain) or ref returns a read-only proxy of the original object. A read-only proxy is “deep”, and any nested properties within an object are also read-only.

const original = reactive({ count: 0 })

const copy = readonly(original)

watchEffect(() = > {
  // Rely on tracing
  console.log(copy.count)
})

// Changes on original trigger listening on copy
original.count++

// Cannot modify copy and will be warned
copy.count++ // warning!
Copy the code

reactiveResponsive system toolset

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

import { reactive, isReactive } from 'vue'
const state = reactive({
      name: 'John'
    })
console.log(isReactive(state)) // -> true
Copy the code

True is also returned if the agent is created by ReadOnly but is wrapped in another agent created by Reactive

import { reactive, isReactive, readonly } from 'vue'
const state = reactive({
      name: 'John'
    })
// Create a read-only reactive plain object with readonly
const plain = readonly({
    name: 'Mary'
})
// Created by readonly, isReactive is false
console.log(isReactive(plain)) // -> false  

// Reactive proxy objects created by Reactive wrap a layer called readonly, which isReactive is true, and isReadonly is true
const stateCopy = readonly(state)
console.log(isReactive(stateCopy)) // -> true
Copy the code

isReadonly

Checks whether an object is a read-only proxy created by ReadOnly

reactiveAdvanced responsive system API

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. It is not recommended to keep a reference to the original object [** it is not recommended to assign to any variable **]. Use with caution

Objects that are toRaw** are normal objects that have not been brokered/traced

const foo = {}
const reactiveFoo = reactive(foo)

console.log(toRaw(reactiveFoo) === foo) // true
console.log(toRaw(reactiveFoo) ! == reactiveFoo)// true
Copy the code

markRaw

This function explicitly marks an object as “never converted to a responsive proxy” and returns the object itself.

MarkRaw passes in an object and returns a value that is never converted to a responsive proxy.

const foo = markRaw({
    name: 'Mary'
})
console.log(isReactive(reactive(foo))) // false
Copy the code

It is marked by markRaw and is not reactive even when used as an attribute in a reactive object

const bar = reactive({ foo })
console.log(isReactive(bar.foo)) // false
Copy the code

markRawPay attention to the point

  • The markRaw and shallowXXX family of apis allow selective override of “deep” features created by reactive or Readonly by default/or use ordinary objects without proxies

  • This “shallow reading” is designed for a number of reasons

    • The actual use of some values is quite simple and does not necessarily require conversion to responsiveness (e.g., tripartite library instance/provincial JSON /Vue component object)
    • When rendering a large number of elements, but the data is immutable, skipping Proxy transformations can provide performance gains
  • These apis are considered advanced because they only stay at the root level, so if you set a nested object with no markRaw to a reactive object’s properties and re-access it, you’ll get a Proxy version, which can eventually lead to serious identity confusion: Performing an operation depends on both the original and the proxy version of an object (identity confusion should be very rare in general use, but a fairly clear understanding of how the overall responsive system works is necessary to completely avoid such a problem).

    const foo = markRaw({
      nested: {},})const bar = reactive({
      // Although 'foo' has been marked as raw, foo.nested is not
      nested: foo.nested,
    })
    
    console.log(foo.nested === bar.nested) // false
    Copy the code
    • Foo.nested is not marked (will never be converted to a reactive proxy), resulting in the final value of a reactive

shallowReactive

Create shallow, responsive proxies for private (layer 1) properties of an object, not deep, recursive, responsive proxies for “properties of properties,” but just as is.

const state = shallowReactive({
  foo: 1.nested: {
    bar: 2,}})// Change state's own property is reactive
state.foo++
/ /... But not deep proxy.
isReactive(state.nested) // false
state.nested.bar++ // non-responsive
Copy the code

shallowReadonly

Similar to shallowReactive, except that:

  • The first layer will be a reactive proxy, and the properties will be reactive
  • Deep object properties can be modified; properties are not reactive
const state = shallowReadonly({
  foo: 1.nested: {
    bar: 2,}})// Changing state's own properties will fail
state.foo++
/ /... But nested objects can be changed
isReadonly(state.nested) // false
state.nested.bar++ // Nested attributes can still be modified
Copy the code

refResponsive system toolset

unref

Unref is val = isRef(val)? Val. value: syntax sugar for val

unref(ref(0))===unref(0) = = =0Returns the numberCopy the code
function useFoo(x: number | Ref<number>) {
  const unwrapped = unref(x) // Unwrapped must be number
}
Copy the code

toRef

ToRefs can be used to create a ref for an attribute of a Reactive object. This REF can be passed and remains responsive

const state = reactive({
  foo: 1.bar: 2,})//reactive gets a single attribute to be a ref
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

const state = reactive({
  foo: 1.bar: 2,})const stateAsRefs = toRefs(state)
/* stateAsRefs types are as follows: {foo: Ref
      
       , bar: Ref
       
        } */
       
      

// The ref object is "linked" to the original attribute
state.foo++
console.log(stateAsRefs.foo) / / 2

stateAsRefs.foo.value++
console.log(state.foo) / / 3
Copy the code

You can return a deconstructible REACTIVE via toRefs because the toRefs package then returns a one-to-one ref property

function useFeatureX() {
  const state = reactive({
    foo: 1.bar: 2,})// Logical operation on state

  // Return all attributes to ref
  return toRefs(state)
}

export default {
  setup() {
    // Can be deconstructed without loss of responsiveness
    const { foo, bar } = useFeatureX()

    return {
      foo,
      bar,
    }
  },
}
Copy the code

isRef

Checks if a value is a ref object

refAdvanced responsive system API

customRef

Use a custom ref to explicitly control the dependency trace and trigger response. Accept a factory function with two parameters: track for trace and trigger for response. And return an object with get and set attributes.

  • The following code will make the V-Model tremble proof
function useDebouncedRef(value, delay = 200) {
  let timeout
  return customRef((track, trigger) = > {
    return {
      get() {
          /* When will dependency collection be triggered
        track()
        return value
      },
      set(newValue) {
          /* The last timer will be cleared when modifying data */
        clearTimeout(timeout)
        timeout = setTimeout(() = > {
            /* Give the newly set data to the ref data source */
          value = newValue
            /* Trigger responsivity */ in case of dependency trace
          trigger()
        }, delay)
      },
    }
  })
}

setup() {
    return {
        /* Expose the returned data plus anti-shake */
      text: useDebouncedRef('hello'),}}Copy the code

shallowRef

A ref is created and its.value changes are tracked, but reactive proxy transformations are not performed on the changed.value.

Refs created by shallowRef will not be called reactive. Refs created by shallowRef will not be called reactive.

const refOne = shallowRef({});
refOne.value = { id: 1 };
refOne.id == 20;
console.log(isReactive(refOne.value),refOne.value);//false { id: 1 }
Copy the code

triggerRef【 withshallowRefCooperate with 】

Manually execute any effects associated with shallowRef

const shallow = shallowRef({
  greet: 'Hello, world'
})

// First run prints "Hello, world"
watchEffect(() = > {
  console.log(shallow.value.greet)
})

// This does not trigger the effect because ref is shallow
shallow.value.greet = 'Hello, universe'

// Print "Hello, universe"
triggerRef(shallow)
Copy the code

Computed and Watch

computed

  • Pass in a getter function that returns a ref object that cannot be manually modified by default.

  • Pass in an object with get and set functions to create a computed state that can be manually modified

const count = ref(1)
/* The [read-only] */ is not supported
const plusOne = computed(() = > count.value + 1)
plusOne.value++ / / error!

/* [modifiable] */
const plusOne = computed({
  get: () = > count.value + 1.set: (val) = > {
    count.value = val - 1
  },
})

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

watchEffect

Execute a function passed in immediately, trace its dependencies responsively, and re-run the function when its dependencies change

Differences between Computed and watchEffect:

  • computedProperties can be evaluated through setupreturnWatchEffect cannot be used in the template.
  • computedMultiple properties can be used, and multiple properties can be evaluated differently in response, and watchEffect has side effects
const count = ref(0)

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

setTimeout(() = > {
  count.value++
  // -> print 1
}, 100)
Copy the code

Stop watch

When watchEffect is called during a component’s Setup () function or lifecycle hook, the monitor links to the component’s lifecycle and stops automatically when the component is uninstalled

In general, watchEffect returns that you can stop the listener

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

// Stop the listener
stop()
Copy the code

Side effects (functional programming)

A function with side effects does more than simply return a value, such as:

  • Modifying a variable
  • Modify the data structure directly
  • Sets the member of an object
  • Throws an exception or terminates with an error
  • Print to a terminal or read user input
  • Read or write to a file
  • Draw on the screen

Examples of buyCoffee (P3) : Function is only need to return to a cup of coffee, but persistence operation of cost (side effects), we can in buyCoffee method returns also along with the cost as the value returned when coffee, will cost the records to other programs for persistence, = = = = > in order to get rid of the side effects by pushing these side effects to the outer layer of the program, To convert any functions with side effects (pure kernel and a thin layer of periphery to handle side effects)

If a function has a dependency on an external variable or environment, we often call it a side effect. We don’t know what the function is doing if we just sign the function without opening the internal code check. As a separate function we expect explicit inputs and outputs. As programmers, developers should develop as few functions or methods as possible that have side effects, which also make methods less generic and less suitable for extensibility and reuse

Clearance side effect

[^]: watchEffect functions are side effects

At some point the listener will perform asynchronous side effects (a reactive dependency has been modified to do something else), and these responses need to be cleared when they fail (such as a state change before the effect is complete). The effect function takes an onInvalidate function as an input parameter that registers callbacks to clean up failures. When will the invalidation function be called:

  • When the listener function is executed again

  • When watchEffect is stopped (the component will be uninstalled if watchEffect is used in setup() or lifecycle functions)

    watchEffect(onInvalidate= > {
      /* This is an asynchronous operation */
      const token = performAsyncOperation(id.value)/ / id
      onInvalidate(() = > {
        // The token.cancel() event is triggered when the id is changed or the listener stops.
        // If this is an asynchronous event, the previous peding asynchronous operation is invalid.
         token.cancel()/* Asynchronous operation */
        console.log('onInvalidate')})})Copy the code
From above: The reason we register the invalidation callback by passing in a function, rather than returning it from the callback (as in React 'useEffect'), ````js const data = ref(null) watchEffect(async onInvalidate => {onInvalidate(() => {... }) // We at Promise's high similarity before cleanup function data.value = await fetchData(props. Id)})Copy the code

We know that asynchronous functions implicitly return a Promise, but the side-effect clearing function must be registered before the Promise can be resolved. In addition, Vue relies on this returned Promise to automatically handle potential errors in the Promise chain

Side effect refresh time

Vue’s reactive system caches side effects functions and refreshes them asynchronously to avoid unnecessary repeated calls due to multiple state changes in the same tick. In the concrete implementation of the core, the component’s update function is also a monitored side effect. When a user-defined side effect function is queued, it is executed after all components are updated

<template>
  <div>{{ count }}</div>
</template>

<script>
  export default {
    setup() {
      const count = ref(0)

      watchEffect(() = > {
        console.log(count.value)
      })

      return {
        count,
      }
    },
  }
</script>
Copy the code
  • Count is printed synchronously at initial run time

  • When count is changed, side effects are performed after the component is updated

    If you want to access DOM (or template ref) when writing side functions, do so in onMounted.

    onMounted(() = > {
      watchEffect(() = > {
        // Here you can access DOM or template refs})})Copy the code

If side effects need to be synchronized or re-run before component updates, we can pass an object with flush property as an option (default ‘POST’)

// Run synchronously
watchEffect(
  () = > {
    / *... * /
  },
  {
    flush: 'sync',})// Execute before component update
watchEffect(
  () = > {
    / *... * /
  },
  {
    flush: 'pre',})Copy the code

Listener debugging [responsive callback trial]

The onTrack and onTrigger options can be used to debug the behavior of a listener.

  • Called when a Reactive object property or a REF is traced as a dependencyonTrack[Number of calls is the number of tracked]
  • Dependency changes cause dependencies to be retraced, thusonTrackCalled [number of calls is the number tracked]
  • Is called when a dependency change causes a side effect to be triggeredonTrigger

Both callbacks will receive a debugger event that contains information about the dependencies. It is recommended to write debugger statements in the following callbacks to check dependencies: onTrack and onTrigger only work in development mode

watchEffect(
  () = > {
    /* Side effects */
  },
  {
    onTrigger(e) {
      /* Side effect dependent modification */
      debugger
    },
    onTrack(e) {
      /* Side effect dependent modification */
      debugger}})Copy the code

watch

The Watch API is exactly equivalent to the corresponding option in 2.x Watch. Watch needs to listen for specific data sources and perform side effects in callback functions (lazy by default, meaning callback is executed only when the source it is listening for changes)

Watch allows us to:

  • Lazy execution side effects
  • Make it clearer which state changes trigger the listener restart side effect
  • Access values before and after listening state changes

Listening to a single data source

The listener’s data source can be a getter function with a return value, or it can be ref:

// Listen for a getter
const state = reactive({ count: 0 })
watch(
  () = > state.count,
  (count, prevCount) = > {
    / *... * /})// Listen directly on a ref
const count = ref(0)
watch(count, (count, prevCount) = > {
  / *... * /
})
Copy the code

Listening to multiple data sources

Watcher can also use arrays to listen for multiple sources at the same time

watch([fooRef, barRef], ([foo, bar], [prevFoo, prevBar]) = > {
  / *... * /
})
Copy the code

withwatchEffectThe act of sharing

Watch and watchEffect behave the same in stopping listening, clearing side effects (onInvalidate is passed in as the third argument to the callback accordingly), side effect refresh timing, and listener debugging

watch([fooRef, barRef], ([foo, bar], [prevFoo, prevBar],onInvalidate) = > {
  / *... * /
  onInvalidate(() = > {...})
},
  {
    onTrigger(e) {
      /* Side effect dependent modification */
      debugger
    },
    onTrack(e) {
      /* Side effect dependent modification */
      debugger}})Copy the code

Lifecycle hook functions

A composite API corresponding to the 2.x release lifecycle

  • beforeCreate– > usesetup()
  • created– > usesetup()
  • beforeMount -> onBeforeMount
  • mounted -> onMounted
  • beforeUpdate -> onBeforeUpdate
  • updated -> onUpdated
  • beforeDestroy -> onBeforeUnmount
  • destroyed -> onUnmounted
  • errorCaptured -> onErrorCaptured
import { onMounted, onUpdated, onUnmounted } from 'vue'
setup() {
    onMounted(() = > {
      console.log('mounted! ')
    })
    onUpdated(() = > {
      console.log('updated! ')
    })
    onUnmounted(() = > {
      console.log('unmounted! ')})}Copy the code

These lifecycle hook registration functions can only be used synchronously during setup() because they rely on internal global state to locate the current component instance (the one that is calling setup()), and not calling these functions on the current component will throw an error.

The component instance context is also set during lifecycle hook synchronization execution, so listeners and computational state created synchronously inside the lifecycle hook are automatically removed when the component is unloaded.

New hook function

In addition to the 2.x lifecycle equivalents, the composite API provides the following debug hook functions:

  • onRenderTracked
  • onRenderTriggered

Both hook functions receive a DebuggerEvent, similar to onTrack and onTrigger in the watchEffect parameter options:

export default {
  onRenderTracked(e){
      debugger
    // Check dependencies with response and trace
 },
  onRenderTriggered(e) {
    debugger
    // Check which dependencies cause the component to be rerendered}},Copy the code

Built-in components provided by Vue

Component is the same as Vue2. X

Renders a “meta-component” as a dynamic component. Determines which component is rendered based on the value of is.

<! < Component :is="componentId"></ Component ><! <component :is="$options.ponents. Child "></component>Copy the code

Transition is the same as Vue2. X

  • Props new:
    • persistedboolean If true, this is a transformation that does not actually insert/delete elements, but instead switches show/hide states. The transition hook is injected but skipped by the renderer. Instead, custom directives can control the transition by calling injected hooks, such as V-show
    • enter-class—–>enter-from-class
    • leave-class—–>leave-from-class
  • The event
    • before-appear

Transition-group is consistent with Vue2. X

Slot Consistent with Vue2. X

Teleport [New Component]

  • Props

    • To-string mandatory property, which must be a valid Query selector or element (if used in a browser environment). Will be placed in the specified target element

      <! -- True --><teleport to="#some-id" />
      <teleport to=".some-class" />
       / * * / elements
      <teleport to="[data-teleport]" /><! -- False --><teleport to="h1" />
      <teleport to="some-string" />
      Copy the code
    • Disabled-boolean This is an optional feature that can be disabled, meaning that its slot contents are not moved anywhere, but rendered as if there were no teleport components. [Default: false]

      <teleport to="#popup" :disabled="displayVideoInline">
        <h1>999999</h1>
      </teleport>
      Copy the code

      Note that this moves the actual DOM nodes rather than destroying and recreating them, and also keeps any component instances active. All stateful HTML elements (such as a playing video) will retain their state. Controlling displayVideoInline does not destroy rebuild, it keeps the instance alive and will not be deregistered.

More about Teleport

Vue encourages us to build uIs by encapsulating THE UI and related behavior into components. We can nest them with each other to build the tree that makes up the application UI

However, sometimes a part of a component template logically belongs to that component, and it is technically best to move that part of the template somewhere else in the DOM, outside of the Vue application

A common scenario is to create a component that contains full-screen modes. In most cases, you want the modal logic to reside in the component, but the positioning of the modal box quickly becomes difficult to solve with CSS, or requires changing the composition of the component

Consider the following HTML structure:

<body>
  <div style="position: relative;">
    <h3>Tooltips with Vue 3 Teleport</h3>
    <div>
      <modal-button></modal-button>
    </div>
  </div>
</body>
Copy the code

Let’s look at mode-Button

This component will have a button element that triggers the opening of the mode, and a div element of class.modal, which will contain the content of the mode and a self-close button

const app = Vue.createApp({});

app.component('modal-button', {
  template: `  
       `.data() {
    return { 
      modalOpen: false}}})Copy the code

When using this component in the initial HTML structure, we can see a problem — the modes are rendered in deeply nested divs, and the absolute position of the mode is referenced by the relative position of the parent div.

Teleport provides a clean way to control which parent node in the DOM we want to render an HTML fragment under, without resorting to global state or splitting it into two components.

Let’s modify our modal-button to use it and tell Vue “teleport this HTML to the “body” tag.

app.component('modal-button', {
  template: `
    <button @click="modalOpen = true">
        Open full screen modal! (With teleport!)
    </button>

    <teleport to="body">
      <div v-if="modalOpen" class="modal">
        <div>
          I'm a teleported modal! 
          (My parent is "body")
          <button @click="modalOpen = false">
            Close
          </button>
        </div>
      </div>
    </teleport>
  `,
  data() {
    return { 
      modalOpen: false
    }
  }
})
Copy the code

Used with Vue components

If a Vue component is included, it will remain a logical child of the parent component

const app = Vue.createApp({
  template: ` 

Root instance

`
}) app.component('parent-component', { template: `

This is a parent component

`
}) app.component('child-component', { props: ['name'].template: `
Hello, {{ name }}
`
}) Copy the code

In this case, even if the Child-Component is rendered in a different place, it will still be a child of parent-Componen and will receive props of name from its parent

This also means that the injection from the parent component works as expected, and that the child component is nested under the parent component of Vue Devtools rather than where the actual content is moved to

Use teleports multiple times for the same target

A common use case scenario is a reusable component that may have multiple active instances at the same time. For this scenario, multiple components can mount their content to the same target element. This order will be a simple add-on — later mounts will follow earlier mounts in the target element.

<teleport to="#modals">
  <div>A</div>
</teleport>
<teleport to="#modals">
  <div>B</div>
</teleport><! -- result--><div id="modals">
  <div>A</div>
  <div>B</div>
</div>
Copy the code

Provide/Inject dependency injection

Provide and inject Provide dependency injection, which is similar to provide/inject of 2.x. Both can only be called in setup() of the currently active component instance

For example, if we want to provide a Book name on the root component and inject it into the child component

import { provide, inject } from 'vue'

const RootComponent = {
  setup() {
    provide('book'.'Vue 3 guide')}}const MyBook = {
  setup() {
    const book = inject(
      'book'.'Eloquent Javascript' The default value of the /* option, which is returned if the parent component does not provide a value
    )
    return {
      book
    }
  }
}
Copy the code

Inject accepts an optional default value as the second parameter. Inject returns undefined if a default value is not provided and the attribute is not found in the provide context.

If we need to provide or inject multiple values, we can do this by subsequently calling provide or Inject, respectively.

import { provide, inject } from 'vue'

const RootComponent = {
  setup() {
    provide('book'.'Vue 3 guide')
    provide('year'.'2020')}}const MyBook = {
  setup() {
    const book = inject(
      'book'.'Eloquent Javascript' The default value of the /* option, which is returned if the parent component does not provide a value
    )
    const year = inject('year')
    return {
      book,
      year
    }
  }
}
Copy the code

Responsiveness of injection

Ref or reactive can be used to ensure the response between provided and injected

import { ref, reactive } from 'vue'

/ / provider
setup() {
  const book = reactive({
    title: 'Vue 3 Guide'.author: 'Vue Team'
  })
  const year = ref('2020')

 /* Provide reactive */
  provide('book', book)
 /* provides the ref response */
  provide('year', year)
}

/ / consumer
setup() {
  const book = inject('book')
  const year = inject('year')
 /* Responsive */
  return { book, year }
}
Copy the code

Now, when book or year changes on the provider component, we can observe their changes on the injected component.

Warning: We do not recommend changing an injected reactive property because it would break the one-way data flow of the Vue. Instead, try to change the value where the parent provides it, or provide a method to change the value

import { ref, reactive } from 'vue'

// in provider
setup() {
  const book = reactive({
    title: 'Vue 3 Guide'.author: 'Vue Team'
  })

  function changeBookName() {
    book.title = 'Vue 3 Advanced Guide'
  }

  provide('book', book)
  provide('changeBookName', changeBookName)
}

// in consumer
setup() {
  const book = inject('book')
  const changeBookName = inject('changeBookName')

  return { book, changeBookName }
}
Copy the code

instruction

V-text [Vue2. X consistent]

V-html [Vue2. X consistent]

V-show [same as Vue2. X]

V-if [Vue2. X consistent]

V-else [Vue2. X consistent]

V-else -if [Vue2. X consistent]

V -for [Vue2. X consistent]

V-on [Vue2. X consistent]

V – bind 【 Vue2. XThe modifierDifferences between 】

The modifier

  • .propGet rid of
  • .syncGet rid of
  • .camelConvert the kebab-case attribute name to camelCase

V-model [ve2. X consistent]

V-slot [same as Vue2. X]

V-cloak 【Vue2. X 】

V-once [Vue2. X consistent]

V-pre [Vue2. X consistent]

V-is [added]

Note: This section only affects the case where the Vue template is written directly in the HTML of the page

  • Limitation: Native HTML elements

  • Use:

    When using an in-DOM template, the template should follow native HTML parsing rules. Certain HTML elements (e.g

      .
      , and) have restrictions on what elements can be displayed in it, and certain elements (for example, and) can only appear in certain other elements. The solution is to use the V-IS directive on these elements.

      Warning the V-IS function is like a dynamic 2.x: IS binding so render the component according to the registered name, whose value should be a JavaScript string

      <! -- Incorrect, no render will appear --><tr v-is="blog-post-row"></tr><! - right - ><tr v-is="'blog-post-row'"></tr>
      Copy the code

      Global API

      createApp

      Returns an application instance that provides an application context. The entire tree of components mounted by the application instance shares the same context

      const app = Vue.createApp({})
      Copy the code

      parameter

    • This function takes a root component option object as its first argument
    const app = Vue.createApp({
      data() {
        return{... }},methods: {... },computed: {... }setup(){...}
      ...
    })
    Copy the code
    • With the second argument, we can pass the root component props to the application
    <div id="app"> <! -- this will be shown here'Evan' -->
      {{ username }}
    </div>
    
    const app = Vue.createApp(
      {
        props: ['username'] {},username: 'Evan'})Copy the code

    h

    Returns a “virtual node,” often abbreviated to VNode: a simple object that contains information describing what type of node a Vue should render on the page, including a description of any child nodes. You can read render functions manually

    render() {
      return Vue.h('h1', {}, 'Some title')}Copy the code

    parameter

    Accepts three parameters tag, props and children

    • tag:

      • Type:String | Object | Function | null
      • Details: an HTML tag name, a component, an asynchronous component or NULL. Render as comments using NULL. This parameter is required
    • props

      • Type:Object
      • Details: Objects corresponding to attributes, props, and Events used in the template. optional
    • children

      • Type: String | Array | Object

      • Details:

        Children VNodes, built using h(), or using a string to get “text VNodes” or an object with slots. optional

    const aaa = {
      props: {
        someProp: String
      },
      setup(props) {
        console.log(props, "dsadasdasddasds");
      },
      render() {
        return h(
          "h2".// {Object}props
            // Objects corresponding to props, Attributes and Events
            // We will use it in template.
            // Optional.
            {style: {"font-size": "20px".color: "# 136"}},this.someProp,this.$slots.default()]); }}; app.component("anchored-heading", {
      render() {
        return h(
            / * / / {String | Object | Function | null} tag / / HTML tag name, component, asynchronous components or null. // Render comments with null. / / required * /
          "h" + this.level, // tag name
            // {Object}props
            // Objects corresponding to props, Attributes and Events
            // We will use it in template.
            // Optional.
          {}, 
            // {String | Array | Object} children
            // Child vNodes built with 'h ()',
            // Or use a string to get text VNodes or
            // Objects with slots.
            // Optional.
          [
            "Some text comes first.",
            h("h1"."A headline"),
            h(aaa, {
              someProp: "foobar"})]); }});Copy the code

     Vue.h(
            'a',
            {
              name: headingId,
              href: The '#' + headingId
            },
            this.$slots.default()
          )
        ])
    Copy the code

    limit

    VNodes must be unique
    • All VNodes in the component tree must be unique. This means that the following render function is invalid

       render() {
           const myParagraphVNode = Vue.h('p'.'hi')
            return Vue.h('div'[// Express surprise - copy VNodes!
              myParagraphVNode, myParagraphVNode
            ])
        }
      Copy the code
    • If you really want to copy the same element/component multiple times, you can do so using the factory function. For example, the following render function is a perfectly valid way to render 20 identical paragraphs:

      render() {
        return Vue.h('div'.Array.apply(null, { length: 20 }).map(() = > {
            return Vue.h('p'.'hi')}}))Copy the code
    Replace template features with plain JavaScript
    v-if and v-for

    This can be done easily with plain JavaScript anywhere, and Vue rendering functions offer no proprietary alternatives. For example, in a template that uses V-if and V-for

    <ul v-if="items.length">
      <li v-for="item in items">{{ item.name }}</li>
    </ul>
    <p v-else>No items found.</p>
    ==>
    props: ['items'].render() {
      if (this.items.length) {
        return Vue.h('ul'.this.items.map((item) = > {
          return Vue.h('li', item.name)
        }))
      } else {
        return Vue.h('p'.'No items found.')}}Copy the code
    v-model

    The V-Model directive is extended to modelValue and onUpdate:modelValue props During template compilation, we will have to provide these props ourselves

    props: ['modelValue'].render() {
      return Vue.h(SomeComponent, {
        modelValue: this.modelValue,
        'onUpdate:modelValue': value= > this.$emit('update:modelValue', value)
      })
    }
    Copy the code
    v-on

    We must provide an appropriate prop name for the event handler; for example, to handle click events, the prop name should be onClick

    render() {
      return Vue.h('div', {
        onClick: $event => console.log('clicked', $event.target)
      })
    }
    Copy the code
    Event modifier

    Vue provides the handler’s object syntax for the. Passive,. Capture, and. Once event modifiers

    render() {
      return Vue.h('input', {
        onClick: {
          handler: this.doThisInCapturingMode,
          capture: true
        },
        onKeyUp: {
          handler: this.doThisOnce,
          once: true
        },
        onMouseOver: {
          handler: this.doThisOnceInCapturingMode,  / / event
          once: true.// Whether to trigger once
          capture: true}})}Copy the code

    For all other events and key modifiers, no special API is required because we can use event methods in our handlers

    render() {
      return Vue.h('input', {
        onKeyUp: event= > {
          // Abort the element to which the event is bound if the element that emitted the event does not exist
          if(event.target ! == event.currentTarget)return
          // Also if the key is not Enter key (13) and the shift key is not down
          if(! event.shiftKey || event.keyCode ! = =13) return
          // Stop event propagation
          event.stopPropagation()
          // Block the default keyup handler for this element
          event.preventDefault()
          // ...}})}Copy the code
    Slots

    You can access the slots content this.$slots in the VNodes array

    render() {
      // `<div><slot></slot></div>`
      return Vue.h('div', {}, this.$slots.default())
    }
    Copy the code
    props: ['message'].render() {
      // `<div><slot :text="message"></slot></div>`
      return Vue.h('div', {}, this.$slots.default({
        text: this.message
      }))
    }
    Copy the code

    Use the Render function to pass the slot to the child component

    render() {
      // `<div><child v-slot="props"><span>{{ props.text }}</span></child></div>`
      return Vue.h('div', [
        Vue.h('child', {}, {
          // through 'slots' as a child object
          // in the form of { name: props => VNode | Array<VNode> }
          default: (props) = > Vue.h('span', props.text)
        })
      ])
    }
    Copy the code
    JSX

    If we have to write a lot of rendering functions, writing something like this can be a pain

    Vue.h(
      'anchored-heading',
      {
        level: 1
      },
      [Vue.h('span'.'Hello'), ' world! '])Copy the code

    Especially when the template version is so compact by comparison

    <anchored-heading :level="1"> <span>Hello</span> world! </anchored-heading>
    Copy the code

    That’s why there is a Babel plug-in that can use JSX in Vue. Let’s go back to more template-like syntax

    import AnchoredHeading from './AnchoredHeading.vue'
    
    new Vue({
      el: '#demo'.render() {
        return (
          <AnchoredHeading level={1}>
            <span>Hello</span> world!
          </AnchoredHeading>)}})Copy the code

    defineComponent

    On the implementation side, defineComponent only performs actions that return the object passed to it. However, in terms of type, the returned value has a synthetic type of the constructor supported by TSX and IDE tools

    parameter

    Object with component options

    import { defineComponent } from 'vue'
    
    const MyComponent = defineComponent({
      data() {
        return { count: 1}},methods: {
        increment() {
          this.count++
        }
      }
    })
    Copy the code

    defineAsyncComponent

    Create asynchronous components that load only when necessary

    parameter

    For basic usage, defineAsyncComponent can accept factory functions that return promises. Promise’s parse callback should be invoked when you retrieve the component definition from serve. You can also call Reject (Reason) to indicate a load failure.

    import { defineAsyncComponent } from 'vue'
    
    
    const AsyncComp = defineAsyncComponent(() = >
       / * or * /
      import('./components/AsyncComponent.vue')
       / * or * /
      new Promise((resolve, reject) = > {
      / * can reject * /
          resolve({
            template: '
            
    I am async!
    '
    }) }) ) app.component('async-component', AsyncComp) Copy the code

    You can also provide a function that returns a Promise directly when using a local registry

    import { createApp, defineAsyncComponent } from 'vue'
    
    createApp({
      // ...
      components: {
        AsyncComponent: defineAsyncComponent(() = >
          import('./components/AsyncComponent.vue'))}})Copy the code

    For advanced usage, defineAsyncComponent can accept an object

    const AsyncComp = defineAsyncComponent({
      // Factory function
      loader: () = > import('./Foo.vue')
      // The component used when loading asynchronous components
      loadingComponent: LoadingComponent,
      // The component used when loading failed
      errorComponent: ErrorComponent,
      // Delay before display loading component. Default value :200 ms.
      delay: 200.// If timeout occurs, an error component is displayed
      // There is a timeout and the time is exceeded. Default value: infinity
      timeout: 3000.// A function that returns a Boolean value indicating whether the asynchronous component should retry when the loader Promise Rejects
      retryWhen: error= >error.code ! = =404.// Maximum number of retries allowed
      maxRetries: 3.// Define whether the component can be mounted
      suspensible: false
    })
    Copy the code

    resolveComponent

    Warning resolveComponent can only be used in render or setup functions.

    Allows resolution of a component by name if it is available in the current application instance. If the component is not found, return the component or undefined component

    If component is not found, return component or undefined component

    app.component('MyComponent', {
      / *... * /
    })
    const MyComponent = resolveComponent('MyComponent')
    Copy the code

    ResolveDynamicComponent [resolve active component]

    ResolveDynamicComponent can only be used in render or setup functions.

    Allows parsing components using the same mechanism as Component :is=””.

    Returns the parsed component or a newly created VNode marked with the component name as the node.

    If the component is not found, a warning is issued

    resolveDirective

    Warning resolveDirective can only be used in render or setup functions.

    Allows resolution of instructions by name if it is available in the current application instance.

    Return a Directive or undefined if not found.

    app.directive('highlight', {})
    render(){
        const highlightDirective = resolveDirective('highlight')}Copy the code

    withDirectives

    Warning withDirectives can only be used in render or setup functions.

    ::: allows application instructions to be applied to a VNode. Returns a VNode with application instructions.

    const bar = resolveDirective('bar')
    
    return withDirectives(h('div'), [
      [bar, this.y]
    ])
    Copy the code

    CreateRenderer * [waiting]

    nextTick

    Defer the callback until after the next DOM update cycle. Use it immediately after you have changed some data to wait for DOM updates

    setup() {
        const message = ref('Hello! ')
        const changeMessage = async newMessage => {
          message.value = newMessage
          /* Wait for DOM update */
          await nextTick()
          console.log('Now DOM is updated')}}Copy the code

    Example methods

    $watch

    parameter

    • {string | Function} source
    • {Function | Object} callback
    • {Object} [options]
      • {boolean} deep
      • {boolean} immediate

    usage

    Observe changes to reactive properties or computed functions on component instances. Use a callback to get the new and old values for a given property. We can only pass attribute names for top-level Data, PROP, or computed as strings. For more complex expressions or nested properties, use functions instead.

    example

    const app = Vue.createApp({
      data() {
        return {
          a: 1.b: 2.c: {
            d: 3.e: 4}}},created() {
        // The top-level attribute name is a
        this.$watch('a'.(newVal, oldVal) = > {
          // Do something
        })
    
        // Observe to monitor a single nested attribute
        this.$watch(
          () = > this.c.d,
          (newVal, oldVal) = > {
            // Do something})// Monitor complex expressions
        this.$watch(
          // every time the expression 'this.a + this.b' yields a different result
          // The handler will be invoked. It's like we're looking at computed properties
          // Do not define the calculated attribute itself
          () = > this.a + this.b,
          (newVal, oldVal) = > {
            // Do something})}})Copy the code
    • When the value being monitored is an object or array, any changes to its attributes or elements will not trigger the monitor because they reference the same object/array
    const app = Vue.createApp({
      data() {
        return {
          article: {
            text: 'Vue is awesome! '
          },
          comments: ['Indeed! '.'I agree']}},created() {
        this.$watch('article'.() = > {
          console.log('Article changed! ')})this.$watch('comments'.() = > {
          console.log('Comments changed! ')})},methods: {
        // These methods do not fire the observer because we only change the object/array properties,
        // Not Object/Array itself
        changeArticleText() {
          this.article.text = 'Vue 3 is awesome'
        },
        addComment() {
          this.comments.push('New comment')},// These methods fire the observer because we have completely replaced the object/array
        changeWholeArticle() {
          this.article = { text: 'Vue 3 is awesome'}},clearComments() {
          this.comments = []
        }
      }
    })
    Copy the code
    • $watch returns an unmonitored function that stops firing the callback
    const unwatch = vm.$watch('a', cb)
    // later, teardown the watcher
    unwatch()
    Copy the code

    Option: deep

    To detect nested value changes within an object, pass deep: true in the options argument. Note that this is not required to listen for array mutations.

    vm.$watch('someObject', callback, {
      deep: true
    })
    vm.someObject.nestedValue = 123
    // Trigger the callback
    Copy the code

    Option: immediate

    Passing immediate: true in the option immediately triggers a callback with the current value of the expression

    vm.$watch('a', callback, {
      immediate: true
    })
    // "callback" is triggered immediately with the current value of "a"
    Copy the code

    Note that with the immediate option, you will not be able to unmonitor a given property in the first callback call.

    // This example is wrong
    const unwatch = vm.$watch(
      'value'.function() {
        doSomething()
        unwatch()
      },
      { immediate: true})Copy the code

    If you still want to call an unwatch function in a callback, you should first check its availability

    const unwatch = vm.$watch(
      'value'.function() {
        doSomething()
        if (unwatch) {
          unwatch()
        }
      },
      { immediate: true})Copy the code

    $emit 【 agree 】

    $forceUpdate

    $nextTick

    Instances of the property

    Vm.$data

    Vm.$props

    Vm.$el

    Vm.$options

    Vm.$parent

    Vm.$root

    $slots vm.$slots

    Vm.$refs

    Vm.$attrs

    Waste:

    vm.$children

    vm.$slots

    vm.$scopedSlots

    vm.$isServer

    vm.$listeners

    Options/Combinations

    Mixins 【 concord 】

    Extends extends

    Provide/inject

    parent【 ghost 】

    Setup [added]

    See on the

    Options/Resources

    Directives [consistent]

    Components 【 agree 】

    filters【 ghost 】

    Options/data

    Data [concord]

    Props 【 agree 】

    Computed [consistent]

    Methods [consistency]

    Watch [agree]

    emits [added]

    details

    A list/hash of custom events that can be emitted from the component. It has a simple array-based syntax and an alternative object-based syntax that allows configuring event validation.

    In object-based syntax, the value of each attribute can be NULL or a validation function. The validation function will receive the additional arguments passed to the emit call. For example, if other arguments to the this.emit call are called. For example, if other arguments to the this.emit call are called. For example, if this.emit(‘foo’,1) is called, the corresponding validator for Foo will receive the argument 1. The validator function should return a Boolean value indicating whether the event parameter is valid.

    const app = Vue.createApp({})
    
    // Array syntax
    app.component('todo-item', {
      emits: ['check'].created() {
        this.$emit('check')}})// Object syntax
    app.component('reply-form', {
      emits: {
        / / is invalid
        click: null./ / effective
        submit: payload= > {
          if (payload.email && payload.password) {
            return true
          } else {
            console.warn(`Invalid submit event payload! `)
            return false}}}})Copy the code

    Hint that events listed in the EMIT option will not be inherited by the root element of the component [