Vue2源码梳理:update的整体实现流程

Vue源码解析之_update函数(六) 在$mount函数中,主要是调用了mountComponent函数,而该函数最后主要是调用了updateComponent函数,上一次我们分析了render函数的功能(主要是利用createElement函数生成vnode),那么_update函数主要做了什么首先,可以看到在'src/core/instance/lifecycle.js'中在Vue原型上定义了私有方法_update,在整个函数中,... 阅读详情

update

  • 回到之间 $mount时,mountComponent 函数的过程,vm._render 是如何创建了一个 VNode
  • 接下来就是要把这个 VNode 渲染成一个真实的 DOM 并渲染出来,这个过程是通过 vm._update 完成的
  • _update 它是一个vue 的私有方法,它把我们的 vnode 渲染成真实的 dom
  • _update的方法,也是原型上的一个方法, 它的定义在 src/core/instance/lifecycle.js 中
    export function lifecycleMixin (Vue: Class<Component>) {
      Vue.prototype._update = function (vnode: VNode, hydrating?: boolean) {
        // 首先它定义一些变量,这些变量实际上都是给之后数据更新时候用的
        // 因为update它的调用实际有两个,一个是我们首次渲染的时候,它会调用update把我们的vnode映射是真实的dom
        // 还有一个就是当我们去改变数据的时候,数据改变也会驱动视图的变化,它同样也会调update方法
        // 可以初步认为它们都是空
        const vm: Component = this
        const prevEl = vm.$el
        const prevVnode = vm._vnode
        const restoreActiveInstance = setActiveInstance(vm)
        vm._vnode = vnode
        // Vue.prototype.__patch__ is injected in entry points
        // based on the rendering backend used.
        // 这个 prevVnode 也是空,它会走到这个逻辑,就是 initial render,否则会走到 updates
        if (!prevVnode) {
          // initial render
          vm.$el = vm.__patch__(vm.$el, vnode, hydrating, false /* removeOnly */)
        } else {
          // updates
          vm.$el = vm.__patch__(prevVnode, vnode)
        }
        restoreActiveInstance()
        // update __vue__ reference
        if (prevEl) {
          prevEl.__vue__ = null
        }
        if (vm.$el) {
          vm.$el.__vue__ = vm
        }
        // if parent is an HOC, update its $el as well
        if (vm.$vnode && vm.$parent && vm.$vnode === vm.$parent._vnode) {
          vm.$parent.$el = vm.$el
        }
        // updated hook is called by the scheduler to ensure that children are
        // updated in a parent's updated hook.
      }
      // ...
    }
    
    • 这里 vm.__patch__ 定义在 src/platforms/web/runtime/index.js 中
      Vue.prototype.__patch__ = inBrowser ? patch : noop
      
      • 这里浏览器环境,才会有 patch, 这里的 inBrowser
        // src/core/util/env.js
        export const inBrowser = typeof window !== 'undefined'
        
      • vue它是可以跑在服务端的,在服务端的 patch 是一个空函数,因为在服务端不会有dom
    • 进入 patch, 定义在 src/platforms/web/runtime/patch.js
      import * as nodeOps from 'web/runtime/node-ops'
      import { createPatchFunction } from 'core/vdom/patch'
      import baseModules from 'core/vdom/modules/index'
      import platformModules from 'web/runtime/modules/index'
      
      // the directive module should be applied last, after all
      // built-in modules have been applied.
      const modules = platformModules.concat(baseModules)
      
      // 这个 patch 方法,调用了这个 createPatchFunction, 返回来是一个函数,特别像高阶函数这样的概念
      // nodeOps 是操作dom的集合方法;而 modules 是 platformModules 和 baseModules,这里定义属性,类和钩子函数等
      
      // 这里才是真正的 patch 函数,vue饶了一个大圈子,为什么会定义在这里
      // 他利用函数柯里化的技巧,一开始传入 nodeOps, modules 都是和平台相关的
      // vue 是跨平台的,可以在node上跑,可以在浏览器上跑,可以在 weex 上
      // 在web上真实操作dom的api 和 weex 上是不同的,虽然最终可以生成同样的 vnode
      // 这块是分离的, 所以 dom操作的api通过参数来传入
      
      // 另外就是 models 模块,它的一些生命周期,在不同的生命周期要做的事情,然后怎么去生成这些模块和我们dom做配合, 这些东西,跟平台也是相关的
      // 这里有 baseModules 和 platformModules
      // 通过函数柯里化,可基于不同参数来干不同的事情,把写代码的差异去搞定
      // 等到真实执行 patch 的时候,就不用考虑平台的区别了
      // 因为我们是把平台差异化的东西都已经在之前抹平了
      
      // 所以这样的话,就可以每次调用这个 patch 的时候,完全不用关心真实操作是什么
      // 因为在之前已经把这个参数提前传入了,相当于通过这种闭包的技巧,实现了对 nodeOps 和 modules 的持有
      // 接下来真实调每次的方法的时候,都不用再去传这些差异化的参数,这就是一个非常好的一个js的编程技巧
      export const patch: Function = createPatchFunction({ nodeOps, modules })
      
      • 进入 createPatchFunction, 定义在 src/core/vdom/patch.js
        // 在patch阶段中,会执行各个钩子
        const hooks = ['create', 'activate', 'update', 'remove', 'destroy']
        
        export function createPatchFunction (backend) {
          let i, j
          const cbs = {}
        
          // 拿到 这两项
          const { modules, nodeOps } = backend
        
          // 将 hooks 遍历到 cbs 对象中保存
          for (i = 0; i < hooks.length; ++i) {
            cbs[hooks[i]] = []
            // 遍历所有模块,拿到所有模块的钩子
            for (j = 0; j < modules.length; ++j) {
              if (isDef(modules[j][hooks[i]])) {
                cbs[hooks[i]].push(modules[j][hooks[i]])
              }
            }
          }
        
          // ... 这里定义了非常多的辅助函数
        
          // 这个patch实际上是传入了四个参数
          // 关注前两个,oldVnode 是 真实的el, vnode 就是vdom, 后面两个都是 false
          return function patch (oldVnode, vnode, hydrating, removeOnly) {
            // 销毁时 return 跳过
            if (isUndef(vnode)) {
              if (isDef(oldVnode)) invokeDestroyHook(oldVnode)
              return
            }
        
            let isInitialPatch = false
            const insertedVnodeQueue = []
        
            // 这个 if 一般不会走到,跳过
            if (isUndef(oldVnode)) {
              // empty mount (likely as component), create new root element
              isInitialPatch = true
              createElm(vnode, insertedVnodeQueue)
            } else {
              // 这里,判断是否是真实的dom,这里是 true
              const isRealElement = isDef(oldVnode.nodeType)
              if (!isRealElement && sameVnode(oldVnode, vnode)) {
                // patch existing root node
                patchVnode(oldVnode, vnode, insertedVnodeQueue, removeOnly)
              } else {
                // 这里执行
                if (isRealElement) {
                  // mounting to a real element
                  // check if this is server-rendered content and if we can perform
                  // a successful hydration.
                  // 这里不是 ssr, 这里走不到
                  if (oldVnode.nodeType === 1 && oldVnode.hasAttribute(SSR_ATTR)) {
                    oldVnode.removeAttribute(SSR_ATTR)
                    hydrating = true
                  }
                  // 这里浏览器dom环境下,也走不到
                  if (isTrue(hydrating)) {
                    if (hydrate(oldVnode, vnode, insertedVnodeQueue)) {
                      invokeInsertHook(vnode, insertedVnodeQueue, true)
                      return oldVnode
                    } else if (process.env.NODE_ENV !== 'production') {
                      warn(
                        'The client-side rendered virtual DOM tree is not matching ' +
                        'server-rendered content. This is likely caused by incorrect ' +
                        'HTML markup, for example nesting block-level elements inside ' +
                        '<p>, or missing <tbody>. Bailing hydration and performing ' +
                        'full client-side render.'
                      )
                    }
                  }
                  // either not server-rendered, or hydration failed.
                  // create an empty node and replace it
                  oldVnode = emptyNodeAt(oldVnode) // 这个方法就是把真实的dom转化为 vnode
                }
        
                // replacing existing element
                const oldElm = oldVnode.elm
                const parentElm = nodeOps.parentNode(oldElm) // 获取父节点
        
                // 这个函数很重要,把vnode挂载到真实dom上
                // create new node
                createElm(
                  vnode,
                  insertedVnodeQueue,
                  // extremely rare edge case: do not insert if old element is in a
                  // leaving transition. Only happens when combining transition +
                  // keep-alive + HOCs. (#4590)
                  oldElm._leaveCb ? null : parentElm,
                  nodeOps.nextSibling(oldElm)
                )
        
                // update parent placeholder node element, recursively
                if (isDef(vnode.parent)) {
                  let ancestor = vnode.parent
                  const patchable = isPatchable(vnode)
                  while (ancestor) {
                    for (let i = 0; i < cbs.destroy.length; ++i) {
                      cbs.destroy[i](ancestor)
                    }
                    ancestor.elm = vnode.elm
                    if (patchable) {
                      for (let i = 0; i < cbs.create.length; ++i) {
                        cbs.create[i](emptyNode, ancestor)
                      }
                      // #6513
                      // invoke insert hooks that may have been merged by create hooks.
                      // e.g. for directives that uses the "inserted" hook.
                      const insert = ancestor.data.hook.insert
                      if (insert.merged) {
                        // start at index 1 to avoid re-invoking component mounted hook
                        for (let i = 1; i < insert.fns.length; i++) {
                          insert.fns[i]()
                        }
                      }
                    } else {
                      registerRef(ancestor)
                    }
                    ancestor = ancestor.parent
                  }
                }
        
                // destroy old node
                if (isDef(parentElm)) {
                  removeVnodes(parentElm, [oldVnode], 0, 0) // 删除旧的节点
                } else if (isDef(oldVnode.tag)) {
                  invokeDestroyHook(oldVnode)
                }
              }
            }
        
            invokeInsertHook(vnode, insertedVnodeQueue, isInitialPatch)
            return vnode.elm
          }
        }
        
        • 进入 createElm
          function createElm (
            vnode,
            insertedVnodeQueue,
            parentElm,
            refElm,
            nested,
            ownerArray,
            index
          ) {
            // 这个一版不会走到,跳过
            if (isDef(vnode.elm) && isDef(ownerArray)) {
              // This vnode was used in a previous render!
              // now it's used as a new node, overwriting its elm would cause
              // potential patch errors down the road when it's used as an insertion
              // reference node. Instead, we clone the node on-demand before creating
              // associated DOM element for it.
              vnode = ownerArray[index] = cloneVNode(vnode)
            }
          
            vnode.isRootInsert = !nested // for transition enter check
            if (createComponent(vnode, insertedVnodeQueue, parentElm, refElm)) {
              return
            }
          
            const data = vnode.data
            const children = vnode.children
            const tag = vnode.tag
            if (isDef(tag)) {
              if (process.env.NODE_ENV !== 'production') {
                if (data && data.pre) {
                  creatingElmInVPre++
                }
                // 这种错误是没有注册组件,却使用组件
                if (isUnknownElement(vnode, creatingElmInVPre)) {
                  warn(
                    'Unknown custom element: <' + tag + '> - did you ' +
                    'register the component correctly? For recursive components, ' +
                    'make sure to provide the "name" option.',
                    vnode.context
                  )
                }
              }
              // 这里生成原生dom节点
              vnode.elm = vnode.ns
                ? nodeOps.createElementNS(vnode.ns, tag)
                : nodeOps.createElement(tag, vnode)
              setScope(vnode)
              
              // 跳过
              /* istanbul ignore if */
              if (__WEEX__) {
                // ...
              } else {
                // 创建子节点
                createChildren(vnode, children, insertedVnodeQueue)
                if (isDef(data)) {
                  invokeCreateHooks(vnode, insertedVnodeQueue)
                }
                insert(parentElm, vnode.elm, refElm)
              }
          
              if (process.env.NODE_ENV !== 'production' && data && data.pre) {
                creatingElmInVPre--
              }
            } else if (isTrue(vnode.isComment)) {
              vnode.elm = nodeOps.createComment(vnode.text)
              insert(parentElm, vnode.elm, refElm)
            } else {
              vnode.elm = nodeOps.createTextNode(vnode.text)
              insert(parentElm, vnode.elm, refElm)
            }
          }
          
          • createElm 的作用是通过虚拟节点创建真实的 DOM 并插入到它的父节点中
          • 这里的 createComponent 方法目的是尝试创建子组件,在当前这个 case 下它的返回值为 false
          • 接下来判断 vnode 是否包含 tag,如果包含,先简单对 tag 的合法性在非生产环境下做校验,看是否是一个合法标签
          • 然后再去调用平台 DOM 的操作去创建一个占位符元素
            vnode.elm = vnode.ns
              ? nodeOps.createElementNS(vnode.ns, tag)
              : nodeOps.createElement(tag, vnode)
            
          • 进入 createChildren
            // createChildren(vnode, children, insertedVnodeQueue)
            function createChildren (vnode, children, insertedVnodeQueue) {
              if (Array.isArray(children)) {
                // 在 dev 环境对节点 key 做校验
                if (process.env.NODE_ENV !== 'production') {
                  checkDuplicateKeys(children)
                }
                for (let i = 0; i < children.length; ++i) {
                  createElm(children[i], insertedVnodeQueue, vnode.elm, null, true, children, i)
                }
              } else if (isPrimitive(vnode.text)) {
                nodeOps.appendChild(vnode.elm, nodeOps.createTextNode(String(vnode.text)))
              }
            }
            
            • 如果是array, 遍历children 递归调用createElm
            • 其实 createChildren 很简单,如果 这个 vnode 还有子节点
            • 就递归调用子节点的 createElm, 一层层去处理
          • 接着再调用 invokeCreateHooks 方法执行所有的 create 的钩子并把 vnode push 到 insertedVnodeQueue 中
            if (isDef(data)) {
              invokeCreateHooks(vnode, insertedVnodeQueue)
            }
            
            function invokeCreateHooks (vnode, insertedVnodeQueue) {
              for (let i = 0; i < cbs.create.length; ++i) {
                cbs.create[i](emptyNode, vnode)
              }
              i = vnode.data.hook // Reuse variable
              if (isDef(i)) {
                if (isDef(i.create)) i.create(emptyNode, vnode)
                if (isDef(i.insert)) insertedVnodeQueue.push(vnode)
              }
            }
            
          • 最终会调用 insert 操作, 定义在 src/core/vdom/patch.js
          • insert 方法把 DOM 插入到父节点中,因为是递归调用
          • 子元素会优先调用 insert,所以整个 vnode 树节点的插入顺序是先子后父
            insert(parentElm, vnode.elm, refElm)
            
            function insert (parent, elm, ref) {
              if (isDef(parent)) {
                if (isDef(ref)) {
                  if (ref.parentNode === parent) {
                    nodeOps.insertBefore(parent, elm, ref)
                  }
                } else {
                  nodeOps.appendChild(parent, elm)
                }
              }
            }
            
            // src/platforms/web/runtime/node-ops.js
            export function insertBefore (parentNode: Node, newNode: Node, referenceNode: Node) {
              parentNode.insertBefore(newNode, referenceNode)
            }
            export function appendChild (node: Node, child: Node) {
              node.appendChild(child)
            }
            
            • 其实就是调用原生 DOM 的 API 进行 DOM 操作
  • 以上,我们可知,update 操作就是 patch 操作,里面的细节其实是非常多的
  • 这里只是梳理整体的调用流程
  • 从 new Vue 到渲染dom到页面的大致过程如下
  • new Vue -> init -> $mount -> compile(可选,存在编译版本) -> render -> vnode -> patch -> dom
前端---【Vue2基础更新:一文看懂生命周期】 Vue里面的生命周期是什么,生命周期是什么意思,图解生命周期。生命周期分为三个阶段:挂载 、更新、销毁。beforeCreate 、created、beforeMount、mounted、beforeUpdate、beforeDestory、destroyed.这些调用钩子的地方。生命周期过程,首先是创建的一个new vue实例,然后对事件或者生命周期进行初始化。然后给VM注入数据或者,完成响应式的数据代理或者数据劫持是什么,图解生命周期。Vue里面的生命周期是什么,不会吧,还有人不知道生命周期 阅读详情

相关推荐

MES车间管理源码解析:从工单到追溯的全流程实现

制造执行系统(MES)是连接企业计划层与车间执行层的核心信息系统,其本质是通过对工单、物料、质量和设备状态的实时管控,实现生产过程的可视化与可追溯。在工程实践中,基于Spring Boot、Vue与MySQL的前后端分离架构,凭借部署简单、易二次开发等优势,成为中小型制造企业搭建车间管理系统的常见选择。本文围绕一套完整的MES车间管理源码展开,梳理从订单拆解、工单下发、车间报工、物料消耗到质量检验与追溯看板的主线业务,重点解读工单状态机设计、乐观锁并发扣减、聚合表优化看板查询等关键技术点,并结合本地运行联调

weixin_32932149的博客 230

Vue自定义指令

自定义指令v-focus光标聚焦、v-color指定文本颜色、v- fontSize指定字体大小

Siobhan_Mxin的博客 2863

生鲜电商毕设实战包:SpringBoot后端 + Vue前端,含论文PPT与一键可运行源码

计算机专业学生可以直接上手的生鲜电商系统毕设资源,后端用SpringBoot开发,前端基于Vue实现,前后端完全分离。提供完整Java源码(含用户管理、商品浏览、购物车、订单处理等核心功能模块)、MySQL建库建表SQL脚本(springbootcug86.sql)、配套毕业论文文档和答辩PPT。项目结构清晰,包含标准Maven配置(pom.xml、mvnw)、Spring Boot主启动类、RESTful接口定义、application.yml配置文件,以及src/main/java业务逻辑和src/ma

neovim7hacker的博客 238

update(十)

Vue 的_update是实例的一个私有方法,它被调用的时机有 2 个,一个是首次渲染,一个是数据更新的时候;由于我们这一章节只分析首次渲染部分,数据更新部分会在之后分析响应式原理的时候涉及。_update方法的作用是把 VNode 渲染成真实的 DOM,它的定义在src/core/instance/lifecycle.js中: Vue.prototype._update ...

weixin_30542079的博客 503

基于Spring Boot+Vue的智慧食堂平台设计与部署全流程解析

在前后端分离架构日益普及的今天,Java Web项目的开发早已从单纯的CRUD转向工程化、体系化的综合实践。Spring Boot作为后端领域的主流框架,凭借自动装配与生态整合能力简化了服务端开发;Vue则以前端组件化和响应式数据流提升了交互体验。而数据库设计更是整个系统的地基,合理的表结构、字段约束与索引策略直接决定业务逻辑的清晰度和数据一致性。此类技术组合广泛适用于餐饮管理、企业OA、校园服务等信息化场景,既考验开发者对分层架构、接口规范、状态管理的理解,也涉及从本地联调到线上部署的全链路落地能力。围绕

weixin_33951761的博客 326

基于Spring Boot与Vue的人才公寓管理系统源码解析

前后端分离架构已成为现代Web应用开发的主流模式,它将前端展示与后端服务解耦,通过RESTful API进行数据交互,显著提升开发效率与系统可维护性。在管理类系统中,Spring Boot凭借自动化配置与生态整合能力,成为Java后端开发的首选框架;Vue则以组件化开发与响应式数据绑定简化复杂页面构建;MySQL作为关系型数据库,为房源、租户、合同等核心业务数据提供可靠存储。基于这三项技术的人才公寓管理系统,完整覆盖了租户管理、房态管理、合同签署、收费统计等典型公寓运营场景。从数据库表结构设计到后端分层实现

weixin_35903223的博客 117

vue中this.$emit(“update:xx“,value)和xx.sync的用法

在vue项目中,正常父子组件传值使用props属性,而且要注意props的单向数据流特点,也即父组件通过props向子组件传值,但子组件不能直接改props里面的值,正常的做法一般是通过$emit向父组件发射一个事件,然后传值,达到子组件想要修改父组件值的目的.vue在后面的版本为了简化写法,推出了.sync的语法糖写法,代码更简洁,达到的效果是一样的...

u010227042的博客 1万+

Vue3实战:企业级应用集成钉钉扫码登录全流程解析

本文详细解析了在Vue3企业级应用中集成钉钉扫码登录的全流程。从钉钉开放平台应用创建与配置,到Vue3前端如何优雅地嵌入并管理扫码组件,再到后端如何安全地处理OAuth 2.0授权码以换取用户信息并完成登录,提供了完整的实战代码与避坑指南。该方案能有效实现安全便捷的单点登录,统一企业身份认证。

weixin_29019241的博客 292

Vue之render构建、调用整体流程

前言 本篇文章是想要探寻下Vue中是如何处理html到vnode以及vnode转换为html的过程,主要是梳理其大概流程,一些细节流程会在单独文章的细究。

玉案轩窗的博客 3661

理想汽车智驾方案介绍 4 World model + 强化学习重建自动驾驶交互环境

本帖将以 DrivingSphere 为例来解析这个过程。

地平线开发者 1921

佳能C3025打印机扫描方法

佳能C3025彩色打印机扫描方法 步骤一、如果打印机处于休眠状态,可按图中标记的按钮唤醒打印机; 然后点击屏幕上的【扫描】 步骤二、扫描类型选择【文件】 步骤三、点击屏幕上的【地址簿】 步骤四、此时屏幕胡看到名字,如果看不到自己的名字,可往下滑动直到看到自己的名字,然后点击自己的名字,再点击右下角的【应用】 步骤五、点击【发送设置】,可看到文件格式为PDF,点击可以选择JPEG的图片格式。...

weixin_46019317的博客 2万+

Naive UI Vue 3(v2)迁移完全指南:从 v1 到 v2 的破坏性变更、组件 API 重命名与迁移清单

> 本文基于仓库根目录下的 [vue3.md](https://link.gitcode.com/i/f444863eb700a1bab447f34e142cd9e6) 迁移文档展开,并结合当前仓库(Naive UI v2.45.2)的源码实现([src/version.ts](https://link.gitcode.com/i/d9799095ccc3d12fe34dd8170aa4914a)

gitblog_00526的博客 1074

汇川机器人与PLC通信-ModbusTCP超详细案例

通过汇川机器人与PLC的ModbusTCP通信项目案例,我们可以了解通讯配置的过程,地址映射的方式,对接信号的转换,运行时序的逻辑等注意事项,帮助我们快速应用到项目中。

weixin_44166380的博客 1万+

深入解析 Vue 异步组件:三种注册方式与源码级实现原理

异步组件是 Vue 减少首屏代码体积、实现按需加载的核心机制。本文以 Vue 2 源码为线索,完整剖析异步组件的注册入口、`resolveAsyncComponent` 状态机、`once` 单次回调包装、`$forceUpdate` 强制重渲染等关键实现,并逐一拆解普通函数、Promise、高级异步组件(loading/error/timeout/delay)三种写法的底层原理。读完本文,你将能

gitblog_06834的博客 190

黑五数据集实战:从消费者行为解码到零售智能决策

零售智能决策依赖对消费者行为的深度理解,其核心在于将结构化字段还原为真实商业动作。本文基于经典Black Friday数据集,系统阐释如何通过字段语义重定义、业务驱动的特征工程、轻量高效模型(如LightGBM)及定制化损失函数,构建可落地的库存预警、流失拦截与动线优化方案。重点融合‘消费人格指纹’与‘生态位稳定性分’两大热词,揭示数据背后的城市引力场、品类竞争网络与决策节奏图谱,为电商、快消及零售从业者提供从数据分析到业务闭环的完整方法论。

weixin_28630185的博客 346

NX二次开发入门必看:手把手教你搭建开发环境

想顺利开展nx二次开发,第一步就是配置好开发环境。本文详细讲解从安装准备到环境调试的完整流程,结合实际操作细节,帮你避开常见坑点,快速进入nx二次开发的实战阶段。

weixin_31569663的博客 1461

基于SpringBoot+Vue的无人超市管理系统源码全解析

无人超市作为新零售典型场景,其软件系统核心在于打通“人、货、场”的数据链路,实现从进店识别、选品加购到自动结算的全流程闭环。在此基础上,一套企业级管理系统通常采用前后端分离架构,后端以SpringBoot提供RESTful接口,结合MyBatis动态SQL处理复杂商品检索与库存扣减;前端通过Vue进行状态管理与页面交互。这种技术组合兼顾开发效率与业务扩展性,能够支撑会员管理、订单事务一致性、防超卖并发控制等关键能力。从工程实践看,无人超市管理系统的价值不仅体现在基础CRUD,更在于物联网设备预留接口、数据看

weixin_42581846的博客 282

电流镜结构实战:从零理解MOS管偏置电路设计(附吴金课程补充)

本文深入解析电流镜结构在MOS管偏置电路设计中的关键作用,从基本原理到实战应用全面覆盖。通过分析偏置电路的核心原理、破解设计难题的实用技巧,以及进阶优化策略,帮助工程师掌握这一模拟电路设计的核心技术。特别适合需要理解电流镜结构和基准电路设计的读者参考学习。

ujm5678901的博客 256

Vue 2.x 核心扩展特性源码解析:event、v-model、slot、keep-alive 与 transition

在本系列对 Vue.js 源码的前几章分析中,我们已经完整梳理了 Vue 的响应式数据驱动与编译渲染机制。而除了这些核心能力之外,Vue 还内置了一系列极具生产力的扩展特性(feature)——`event` 事件体系、`v-model` 双向绑定、`slot` 插槽、`keep-alive` 组件缓存、`transition` / `transition-group` 过渡动画等。深入理解这些特

gitblog_00795的博客 235

2026年广东省职业院校技能大赛中职组“大数据应用与服务”样题一完整参考答案

2026年广东省职业院校技能大赛中职组“大数据应用与服务”样题一完整参考答案

我是网络安全兼技能大赛工程师,专注网络安全技术学习与技能大赛实战!持续分享最新的技术文章,帮你少走弯路,一起在技术赛道上进步~ 756

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

uni-number-box 数字输入框:从 changelog 看版本演进与源码实现解析

`uni-number-box` 是 uni-app 生态中经典的「带加减按钮的数字输入框」组件,广泛用于购物车加减商品数量、订单数量调整等场景。本文以 hello-uniapp 仓库中 [uni-number-box 的 changelog](https://link.gitcode.com/i/3349bae6ceb200a409f84c62bbd6dfe6) 为骨架,逐版本梳理该组件从 1.

gitblog_00814的博客 1050

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

ant-design-vue Segmented 分段控制器完全指南:API、源码原理与实战示例

Segmented 是 ant-design-vue 中一个用于展示多个选项并允许用户选择单个选项的组件,当切换选中项时,关联区域内容随之变化,常用于「今日 / 本周 / 本月」这类视图切换场景。本文以官方文档([components/segmented/index.zh-CN.md](https://link.gitcode.com/i/ba8f738df4ab3d018233474dd2436

gitblog_00057的博客 388

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

Vue Native 组件 API 兼容性全景指南:在 React 运行时中使用 Vue 组件

> Vue Native 是一个基于 JavaScript 构建跨平台原生移动应用的框架。其核心思路是:**Vue 组件实际上运行在 React 运行时(React Native / React DOM)之上**。因此,你无法访问 VNode(虚拟节点),也无法使用 render 函数;反之,只要你的既有 Vue 组件不依赖这两样东西,它大概率可以直接在 React 环境中运行。本文依据仓库根目录

gitblog_00950的博客 462

Vue 完整版系统知识文档

《Vue全栈开发实战手册》摘要 本手册系统整合Vue2/Vue3全栈知识体系,涵盖基础语法、组件开发、状态管理、工程化等核心内容,适合从入门到精通的完整学习路径。主要特点: 基础核心 详解MVVM架构和响应式原理(Vue2的Object.defineProperty vs Vue3的Proxy) 完整模板语法规则与16种内置指令解析 组件系统核心:通信机制(8种方案)、插槽、动态组件、递归组件 进阶实战 状态管理:Vuex/Pinia完整解决方案 路由开发:动态路由、权限控制、懒加载 工程化:Webpack

专注 Java 后端开发,分享基础语法、JVM、并发、Spring 全家桶、微服务、分布式、性能优化等实战干货。坚持输出高质量技术笔记,用简单语言讲清复杂原理,助力每一位 Java 开发者稳步进阶。 403

vue笔记

监听字符串、数字、布尔值等简单数据类型时,直接在watch中定义与数据同名的属性,属性值为处理函数(接收两个参数:新值newVal和旧值oldValdata() {return {username: '', // 简单数据age: 18},watch: {// 监听 username 的变化console.log('用户名从', oldVal, '变成了', newVal);},// 监听 age 的变化。

2301_79775040的博客 4301

SpringBoot2+Vue3企业OA系统源码解析与部署实战

企业级应用开发中,权限管理、流程审批与数据持久化是构建信息系统的核心议题。SpringBoot作为主流Java后端框架,凭借自动装配与生态整合能力,简化了服务端架构搭建;Vue3的组合式API与工程化特性,则为前端交互提供了高效响应方案。结合MyBatis-Plus对单表操作的极致封装与MySQL8.0在字符集、性能上的增强,一套轻量而完整的前后端分离解决方案得以成型。这套技术组合广泛应用于中小型公司OA、CRM、HRM等业务系统,能够帮助企业快速落地从权限模型到审批流的完整闭环。文章基于实际项目,系统讲解

weixin_33417488的博客 266
上一篇: Vue2源码梳理:vdom结构与createElement的实现
下一篇: React18原理: React核心对象之ReactElement对象和Fiber对象
Wang's Blog
博客等级 码龄12年 7434粉丝 2421原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Wang's Blog

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值