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
config
The 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 to
setup
The returned ref is automatically untangled in the template without writing.value
【setup
Internal 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
props
As 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 use
props
More scenarios, sometimes even just useprops
- will
props
As the first argument, it is possible to make TypeScript pairsprops
Type inference alone is not confused with other attributes in the context. It also makessetup
、render
Be 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
- Components use
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 JavaScript
Declare the underlying type variable
withObject variables
Is used differentlyref
和reactive
- All over the place
reactive
Then 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
reactive
Responsive 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
reactive
Advanced 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
markRaw
Pay 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
ref
Responsive 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
ref
Advanced 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
【 withshallowRef
Cooperate 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:
computed
Properties can be evaluated through setupreturn
WatchEffect cannot be used in the template.computed
Multiple 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 dependency
onTrack
[Number of calls is the number of tracked] - Dependency changes cause dependencies to be retraced, thus
onTrack
Called [number of calls is the number tracked] - Is called when a dependency change causes a side effect to be triggered
onTrigger
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
withwatchEffect
The 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
– > usebeforeCreate
setup()
– > usecreated
setup()
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:
persisted
–boolean
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: `
I'm a modal!
`.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
Get rid of.prop
Get rid of.sync
.camel
Convert 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
- Type:
-
props
- Type:
Object
- Details: Objects corresponding to attributes, props, and Events used in the template. optional
- Type:
-
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
andv-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 codeYou 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.$childrenvm.$slotsvm.$scopedSlotsvm.$isServervm.$listenersOptions/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 [