This is the seventh day of my participation in the First Challenge 2022. For details: First Challenge 2022.
The biggest difference between Vue3 and Vue2 is the introduction of the Composition API
Composition API experience
<body>
<div id="app">
<h1>vue3 composition API</h1>
<p>{{ counter }}</p>
</div>
<script>
const app = Vue.createApp({
setup(props, { emit, slots, attrs }) {
const counter = Vue.ref(0)
Vue.onMounted(() = > {
setInterval(() = > {
counter.value++
}, 1000)})return {
counter
}
}
})
app.mount('#app')
</script>
</body>
Copy the code
Look at the source code with doubt
- When is the Componsition API(Setup) executed?
setup
Why can not usecreated
Life cycle?- The setup parameters passed in are props and CTX, respectively. Where and what are they from?
- You can explore it step by step, starting with mount, in the previous articleVue3.0 source code learning — initialization process analysis (3. Patch process), understand that the mount process will execute the rendering function
render
And will experiencepatch
The first mount will goprocessComponent
= >mountComponent
Position,packages\runtime-core\src\component.ts
mountComponent
Initializes the component (root component) instance insetupComponent(instance)
Here the instance of the component is already created, so it doesn’t make sense to use beforeCreate and created in setup
const mountComponent: MountComponentFn = (
initialVNode, // Root component vnode
container,
anchor,
parentComponent,
parentSuspense,
isSVG,
optimized
) = > {
// 2.x compat may pre-create the component instance before actually
/ / compatible vue2. X
// mounting
const compatMountInstance =
__COMPAT__ && initialVNode.isCompatRoot && initialVNode.component
// 1. Create a component instance, specifically an instance of the root component
const instance: ComponentInternalInstance =
compatMountInstance ||
(initialVNode.component = createComponentInstance(
initialVNode,
parentComponent,
parentSuspense
))
...
// resolve props and slots for setup context
// Handle the setup context
if(! (__COMPAT__ && compatMountInstance)) {if (__DEV__) {
startMeasure(instance, `init`)}// Initialize the component instance, equivalent to _init() in vue2 source code
setupComponent(instance)
if (__DEV__) {
endMeasure(instance, `init`)}}... }Copy the code
setupComponent
Will return asetupResult
=setupStatefulComponent
Is the user configurationsetup
In the functionreturn
The value of the
export function setupComponent(
instance: ComponentInternalInstance,
isSSR = false
) {
isInSSRComponentSetup = isSSR
const { props, children } = instance.vnode
// Whether there are stateful components, non-functional components
const isStateful = isStatefulComponent(instance)
// Initialize props and slots
initProps(instance, props, isStateful, isSSR)
initSlots(instance, children)
// If the component is stateful, perform state initialization and return the setup option return value
const setupResult = isStateful
? setupStatefulComponent(instance, isSSR)
: undefined
isInSSRComponentSetup = false
return setupResult
}
Copy the code
setupStatefulComponent
To get the componentssetup
configuration
Setup is performed via callWithErrorHandling and the props and context context are passed in on the instance
function setupStatefulComponent(instance: ComponentInternalInstance, isSSR: boolean) {
const Component = instance.type as ComponentOptions
...
// 2. call setup()
const { setup } = Component
// If the user sets the setup function
if (setup) {
// Create a context object for the setup function
const setupContext = (instance.setupContext =
setup.length > 1 ? createSetupContext(instance) : null)
// Set the instance of the current component to vue.getCurrentInstance
setCurrentInstance(instance)
// Pause tracing to improve performance
pauseTracking()
Exceptions can be caught by calling setup() with callWithErrorHandling
const setupResult = callWithErrorHandling(
setup,
instance,
ErrorCodes.SETUP_FUNCTION,
// Here is the props for setup(), CTX context
[__DEV__ ? shallowReadonly(instance.props) : instance.props, setupContext]
)
resetTracking()
unsetCurrentInstance()
if (isPromise(setupResult)) {
...
} else {
If setup() does not return a Promise, the result handler is executed
handleSetupResult(instance, setupResult, isSSR)
}
} else{... }}Copy the code
You can see the incoming CTX context in step debugging