| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111 |
- import {
- ComponentInternalInstance,
- FunctionalComponent,
- Data
- } from './component'
- import { VNode, normalizeVNode, createVNode, Comment } from './vnode'
- import { ShapeFlags } from './shapeFlags'
- import { handleError, ErrorCodes } from './errorHandling'
- import { PatchFlags } from '@vue/shared'
- // mark the current rendering instance for asset resolution (e.g.
- // resolveComponent, resolveDirective) during render
- export let currentRenderingInstance: ComponentInternalInstance | null = null
- export function renderComponentRoot(
- instance: ComponentInternalInstance
- ): VNode {
- const {
- type: Component,
- vnode,
- renderProxy,
- props,
- slots,
- attrs,
- emit
- } = instance
- let result
- currentRenderingInstance = instance
- try {
- if (vnode.shapeFlag & ShapeFlags.STATEFUL_COMPONENT) {
- result = normalizeVNode(instance.render!.call(renderProxy))
- } else {
- // functional
- const render = Component as FunctionalComponent
- result = normalizeVNode(
- render.length > 1
- ? render(props, {
- attrs,
- slots,
- emit
- })
- : render(props, null as any)
- )
- }
- } catch (err) {
- handleError(err, instance, ErrorCodes.RENDER_FUNCTION)
- result = createVNode(Comment)
- }
- currentRenderingInstance = null
- return result
- }
- export function shouldUpdateComponent(
- prevVNode: VNode,
- nextVNode: VNode,
- optimized?: boolean
- ): boolean {
- const { props: prevProps, children: prevChildren } = prevVNode
- const { props: nextProps, children: nextChildren, patchFlag } = nextVNode
- if (patchFlag > 0) {
- if (patchFlag & PatchFlags.DYNAMIC_SLOTS) {
- // slot content that references values that might have changed,
- // e.g. in a v-for
- return true
- }
- if (patchFlag & PatchFlags.FULL_PROPS) {
- // presence of this flag indicates props are always non-null
- return hasPropsChanged(prevProps!, nextProps!)
- } else if (patchFlag & PatchFlags.PROPS) {
- const dynamicProps = nextVNode.dynamicProps!
- for (let i = 0; i < dynamicProps.length; i++) {
- const key = dynamicProps[i]
- if (nextProps![key] !== prevProps![key]) {
- return true
- }
- }
- }
- } else if (!optimized) {
- // this path is only taken by manually written render functions
- // so presence of any children leads to a forced update
- if (prevChildren != null || nextChildren != null) {
- return true
- }
- if (prevProps === nextProps) {
- return false
- }
- if (prevProps === null) {
- return nextProps !== null
- }
- if (nextProps === null) {
- return prevProps !== null
- }
- return hasPropsChanged(prevProps, nextProps)
- }
- return false
- }
- function hasPropsChanged(prevProps: Data, nextProps: Data): boolean {
- const nextKeys = Object.keys(nextProps)
- if (nextKeys.length !== Object.keys(prevProps).length) {
- return true
- }
- for (let i = 0; i < nextKeys.length; i++) {
- const key = nextKeys[i]
- if (nextProps[key] !== prevProps[key]) {
- return true
- }
- }
- return false
- }
|