当前位置: 首页 > news >正文

什么是垂直型网站安徽seo

什么是垂直型网站,安徽seo,一般纳税人网站建设多少税率,WordPress感觉很慢Vue3源码系列文章目录 目录 Vue3源码系列文章目录 目录 目录 Vue3源码系列文章目录 前言 一、vue3中createApp()实例是如何创建的,实例是什么样子的? 1、以todoMvc为入口,进行断点调试 2、 其调用了工厂函数ensureRenderer()内部的creat…

Vue3源码系列文章目录

目录

Vue3源码系列文章目录

目录

目录

Vue3源码系列文章目录

前言

一、vue3中createApp()实例是如何创建的,实例是什么样子的?

        1、以todoMvc为入口,进行断点调试

        2、 其调用了工厂函数ensureRenderer()内部的createApp函数, 进入ensureRenderer

         3、ensureRenderer()工厂函数内容据说是vue3中最多的,纠结过程容易迷路,此处直接跳转到该工厂函数返回的结果, 

 4、找到createAppApi()

5、工厂函数创建的app是这个样子

 二、vue3中app.mount(), 挂载都做了什么?

1、创建节点vnode

2、创建render函数并执行render函数, 第一步生成vnode传递给patch函数转换成dom,然后将其添加到宿主上

 挂载时做了: 将传入的组件数据和状态转换成DOM,并追加到宿主元素上

三、patch状态更新流程

1、从状态更新处打断点

 2、单点进入后进入更新状态counter   此处应该是counter = this.counter += 1  会先走get 拿值, 然后走set赋值

3、 单点产看更新,最终走trigger通过!hadkey判断其走trigger Add(添加), 还是走trigger Set(更新)

 4、单点进入trigger Set

 5、走triggerEffect / triggerEffects

 6、走triggerEffect后进入effect.schedule查看其如何更新

 7、单点进入,  激活响应式, 此处想看断点应该打在componentUpdateFn

 8、最后走patch更新 对比prevTree和nextTree哪里不同然后去更新

四、Vue3 Composition Api 探究

1、Composition Api包括:

2、结合reactive、生命周期钩子、属性和上下文进行体验

五、Vue3 ReractiveApi探究



前言

学习源码的笔记,以及vue3源码学习过程的问题、思路、总结。知识是容易遗忘的,让其留下痕迹,方便以后回顾学习。


一、vue3中createApp()实例是如何创建的,实例是什么样子的?

        1、以todoMvc为入口,进行断点调试

        2、 其调用了工厂函数ensureRenderer()内部的createApp函数, 进入ensureRenderer

         3、ensureRenderer()工厂函数内容据说是vue3中最多的,纠结过程容易迷路,此处直接跳转到该工厂函数返回的结果, 

 4、找到createAppApi()

5、工厂函数创建的app是这个样子

export function createAppAPI<HostElement>(render: RootRenderFunction<HostElement>,hydrate?: RootHydrateFunction
): CreateAppFunction<HostElement> {return function createApp(rootComponent, rootProps = null) {if (!isFunction(rootComponent)) {rootComponent = { ...rootComponent }}if (rootProps != null && !isObject(rootProps)) {__DEV__ && warn(`root props passed to app.mount() must be an object.`)rootProps = null}const context = createAppContext()const installedPlugins = new Set()let isMounted = falseconst app: App = (context.app = {_uid: uid++,_component: rootComponent as ConcreteComponent,_props: rootProps,_container: null,_context: context,_instance: null,version,get config() {return context.config},set config(v) {if (__DEV__) {warn(`app.config cannot be replaced. Modify individual options instead.`)}},use(plugin: Plugin, ...options: any[]) {if (installedPlugins.has(plugin)) {__DEV__ && warn(`Plugin has already been applied to target app.`)} else if (plugin && isFunction(plugin.install)) {installedPlugins.add(plugin)plugin.install(app, ...options)} else if (isFunction(plugin)) {installedPlugins.add(plugin)plugin(app, ...options)} else if (__DEV__) {warn(`A plugin must either be a function or an object with an "install" ` +`function.`)}return app},mixin(mixin: ComponentOptions) {if (__FEATURE_OPTIONS_API__) {if (!context.mixins.includes(mixin)) {context.mixins.push(mixin)} else if (__DEV__) {warn('Mixin has already been applied to target app' +(mixin.name ? `: ${mixin.name}` : ''))}} else if (__DEV__) {warn('Mixins are only available in builds supporting Options API')}return app},component(name: string, component?: Component): any {if (__DEV__) {validateComponentName(name, context.config)}if (!component) {return context.components[name]}if (__DEV__ && context.components[name]) {warn(`Component "${name}" has already been registered in target app.`)}context.components[name] = componentreturn app},directive(name: string, directive?: Directive) {if (__DEV__) {validateDirectiveName(name)}if (!directive) {return context.directives[name] as any}if (__DEV__ && context.directives[name]) {warn(`Directive "${name}" has already been registered in target app.`)}context.directives[name] = directivereturn app},mount(rootContainer: HostElement,isHydrate?: boolean,isSVG?: boolean): any {if (!isMounted) {// #5571if (__DEV__ && (rootContainer as any).__vue_app__) {warn(`There is already an app instance mounted on the host container.\n` +` If you want to mount another app on the same host container,` +` you need to unmount the previous app by calling \`app.unmount()\` first.`)}const vnode = createVNode(rootComponent as ConcreteComponent,rootProps)// store app context on the root VNode.// this will be set on the root instance on initial mount.vnode.appContext = context// HMR root reloadif (__DEV__) {context.reload = () => {render(cloneVNode(vnode), rootContainer, isSVG)}}if (isHydrate && hydrate) {hydrate(vnode as VNode<Node, Element>, rootContainer as any)} else {render(vnode, rootContainer, isSVG)}isMounted = trueapp._container = rootContainer// for devtools and telemetry;(rootContainer as any).__vue_app__ = appif (__DEV__ || __FEATURE_PROD_DEVTOOLS__) {app._instance = vnode.componentdevtoolsInitApp(app, version)}return getExposeProxy(vnode.component!) || vnode.component!.proxy} else if (__DEV__) {warn(`App has already been mounted.\n` +`If you want to remount the same app, move your app creation logic ` +`into a factory function and create fresh app instances for each ` +`mount - e.g. \`const createMyApp = () => createApp(App)\``)}},unmount() {if (isMounted) {render(null, app._container)if (__DEV__ || __FEATURE_PROD_DEVTOOLS__) {app._instance = nulldevtoolsUnmountApp(app)}delete app._container.__vue_app__} else if (__DEV__) {warn(`Cannot unmount an app that is not mounted.`)}},provide(key, value) {if (__DEV__ && (key as string | symbol) in context.provides) {warn(`App already provides property with key "${String(key)}". ` +`It will be overwritten with the new value.`)}context.provides[key as string | symbol] = valuereturn app}})if (__COMPAT__) {installAppCompatProperties(app, context, render)}return app}
}

 二、vue3中app.mount(), 挂载都做了什么?

1、创建节点vnode

2、创建render函数并执行render函数, 第一步生成vnode传递给patch函数转换成dom,然后将其添加到宿主上

 - 

 app.mount('#app')

 挂载时做了: 将传入的组件数据和状态转换成DOM,并追加到宿主元素上

三、patch状态更新流程

以下面代码为例子

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title></head>
<body><div id="app"><h1>vue3 更新流程</h1><p>{{counter}}</p><comp></comp></div><script src="../dist/vue.global.js"></script><script>// vue2: new Vue({}).$mount()// 变化1: 函数创建实例// vue3: createApp({})const app = Vue.createApp({// render() {//   return Vue.h('div', {//     myprop, title, onClick//   })// }data() {return {counter: 1}},mounted() {setInterval(() => {this.counter++}, 1000)}})// 变化2: 实例方法app.component('comp', {template: '<div>comp</div>'})// 变化3: 挂载mountapp.mount('#app')  </script>
</body>
</html>

1、从状态更新处打断点

 2、单点进入后进入更新状态counter   此处应该是counter = this.counter += 1  会先走get 拿值, 然后走set赋值

 

 此处data是proxy对象, key是counter

3、 单点产看更新,最终走trigger通过!hadkey判断其走trigger Add(添加), 还是走trigger Set(更新)

 4、单点进入trigger Set

进入后进入

 5、走triggerEffect / triggerEffects

 

 6、走triggerEffect后进入effect.schedule查看其如何更新

 7、单点进入,  激活响应式, 此处想看断点应该打在componentUpdateFn

更新走componentUpdateFn所以断点要提前打在componentUpdateFn的elese update上

 启动queueFlush()只启动一次就行了, 说是启动一个异步任务

 

此处可以看到调用栈的promise 异步任务  此时跟初始化非常相似,多了一个上一次执行的结果

 可以打到下面nexttree查看 nexttree中的count 加1了

 8、最后走patch更新 对比prevTree和nextTree哪里不同然后去更新

四、Vue3 Composition Api 探究

1、Composition Api包括:

  1. setup
  2. 生命周期钩子
  3. getCurrentInstance
  4. provide/inject

问题1: 执行的时刻? 为什么没有created钩子?

  •         从何看起, 首次执行mount挂载, 调用render函数,render内部 调用patch函数进行dom的渲染与更新, patch内部调用processComponent跟组件初始化开始, 从这开始,

 

  • 进入下一步mountComponent

 

  • 进入后首先创建了实例instance,然后进行组件实例初始化setupComponent(instance)  

 

  • 进入组件初始化列表 , 如果组件有状态,执行初始化过程, 并返回setup选项的返回值

  • 看一下如果组件有状态,是如何处理返回setup的返回值的, 此处可以看到将ctx进行proxy代理, 下面是从组件中拿出创建的setup, 如果有就创建setup上下文将 其存入instance.setupContext

 

  •  查看创建setup上下文, 就可以看到context中为什么有四个属性,且为什么attrs是只读的
export function createSetupContext(instance: ComponentInternalInstance
): SetupContext {// 对外暴露接口const expose: SetupContext['expose'] = exposed => {if (__DEV__ && instance.exposed) {warn(`expose() should be called only once per setup().`)}instance.exposed = exposed || {}}//组件非属性特性let attrs: Dataif (__DEV__) {// We use getters in dev in case libs like test-utils overwrite instance// properties (overwrites should not be done in prod)return Object.freeze({get attrs() {return attrs || (attrs = createAttrsProxy(instance))},get slots() {return shallowReadonly(instance.slots)},get emit() {return (event: string, ...args: any[]) => instance.emit(event, ...args)},expose})} else {//返回的就是setupContextreturn {// 只读的attrsget attrs() {return attrs || (attrs = createAttrsProxy(instance))},slots: instance.slots,emit: instance.emit,expose}}
}
  • 继续回到setup, 可以看到setCurrentInstance

  •  下面开始调用setup, 此时传入instance.props, 和setupContext, 这就是为什么setup中有两个参数

 

export function handleSetupResult(instance: ComponentInternalInstance,setupResult: unknown,isSSR: boolean
) {// 首先判断返回的结果是不是函数//如果是函数则作为render函数处理if (isFunction(setupResult)) {// setup returned an inline render functionif (__SSR__ && (instance.type as ComponentOptions).__ssrInlineRender) {// when the function's name is `ssrRender` (compiled by SFC inline mode),// set it as ssrRender instead.instance.ssrRender = setupResult} else {instance.render = setupResult as InternalRenderFunction}} else if (isObject(setupResult)) {if (__DEV__ && isVNode(setupResult)) {warn(`setup() should not return VNodes directly - ` +`return a render function instead.`)}// setup returned bindings.// assuming a render function compiled from template is present.if (__DEV__ || __FEATURE_PROD_DEVTOOLS__) {instance.devtoolsRawSetupState = setupResult}// 如果是对象, 转换setupoResult这个对象为响应式对象// 将来组件渲染函数中会首先从setupState中获取值instance.setupState = proxyRefs(setupResult)if (__DEV__) {exposeSetupStateOnRenderContext(instance)}} else if (__DEV__ && setupResult !== undefined) {warn(`setup() should return an object. Received: ${setupResult === null ? 'null' : typeof setupResult}`)}// 最后依然执行组件的安装// 里面主要是处理其他的options apifinishComponentSetup(instance, isSSR)
}
  • 查看finishComponentSetup(instance, isSSR), 可得知为什么不需要created()

回答: 执行时刻beforeCreate之类的传统生命周期钩子,实际上setup函数执行的时候,组件实例已经创建了,所以setup中处理beforeCreate和created是没有意义的。

问题2: 传入setup参数中的props和ctx从何而来? 又是什么?

问题3: 如果和data这些数据发生冲突,他们能共存吗,Vue3处理时的行为?

setup优先级更高一些,两者可以共存, 为什么setup优先级更高,如何处理的?

2、结合reactive、生命周期钩子、属性和上下文进行体验

五、Vue3 ReractiveApi探究

http://www.khdw.cn/news/6517.html

相关文章:

  • 太原做网站排名网站推广策略
  • 免费ppt模板300套网站seo查询站长之家
  • 假发网站是怎么做的网站运营主要做什么工作
  • 河南省建设监理网站中国网站建设公司前十名
  • 建网站公司销售关键词的选取原则
  • 韶关专业网站建设教程营销培训总结
  • 做网站虚拟主机规格雅思培训班价格一览表
  • 做彩票网站都是怎么拉人的seo推广技术
  • 十堰百度网站建设seo引擎优化是什
  • 平面设计软件cad公众号微博seo
  • wordpress做导航页面模板下载行者seo
  • 长沙app网页开发全面落实疫情防控优化措施
  • 网站开发部门工资会计分录网络营销和电子商务的区别
  • 电商网站设计培训廊坊百度快照优化哪家服务好
  • 免费做拍卖网站网页设计个人主页
  • 织梦个人网站企业培训的目的和意义
  • 网站外网访问怎么做路由器端口映射关键词优化推广策略
  • 公司管理网站首页做网站哪个公司最好
  • api网站制作长沙网站优化seo
  • 长春市住房建设局网站宣传软文案例
  • 用vscode做网站网店推广的重要性
  • eclipse静态网站开发海口关键词优化报价
  • 武汉大学人民医院东院官网seo优化的基本流程
  • 叶涛网站推广优化免费seo工具大全
  • 佛山网站搭建费用百度平台订单查询
  • 桂林做网站公司有哪些seo网站整站优化
  • 网站策划与设计保定关键词优化软件
  • 做网站不给钱宁波seo网络推广外包报价
  • 展览展示设计网站百度推广客服电话人工服务
  • 网站动态logo怎么做甘肃网站推广