我的编程空间,编程开发者的网络收藏夹
学习永远不晚

Vue响应式流程及原理是什么

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

Vue响应式流程及原理是什么

本文小编为大家详细介绍“Vue响应式流程及原理是什么”,内容详细,步骤清晰,细节处理妥当,希望这篇“Vue响应式流程及原理是什么”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。

一、组件化流程

1. 整个new Vue阶段做了什么?

  • 执行init操作。包括且不限制initLifecycleinitState

  • 执行mount。进行元素挂载

  • compiler步骤在runtime-only版本中没有。

    • compiler步骤对template属性进行编译,生成render函数。

    • 一般在项目中是在.vue文件开发,通过vue-loader处理生成render函数。

执行render。生成vnode

<div id="app">{{ message }}</div>
render (h) {  return h('div', {     attrs: {        id: 'app'      },  }, this.message)}
  • render例子,如下

  • 对应手写的render函数

  • patch。新旧vnode经过diff后,渲染到真实dom上

Vue响应式流程及原理是什么

2. 普通dom元素如何渲染到页面?

  • 执行$mount

    • 实际执行mountComponent

    • 这里会实例化一个Watcher

    • Watcher中会执行get方法,触发updateComponent

  • 执行updateComponent。执行vm._update(vm._render(), hydrating)

  • 执行vm.render()

    • render其实调用createElment(h函数)

    • 根据tag的不同,生成组件、原生VNode并返回

  • 执行vm.update()createElm() 到 createChildren() 递归调用

  • 将VNode转化为真实的dom,并且最终渲染到页面

Vue响应式流程及原理是什么

3. 组件如何渲染到页面?

这里以如下代码案例讲解更加清晰~没错,就是这么熟悉!就是一个初始化的Vue项目

// mian.jsimport Vue from 'vue'import App from './App.vue'new Vue({  render: h => h(App),}).$mount('#app')
// App.vue<template>    <div id="app">      <p>{{ msg }}</p>    </div></template><script>    export default {        name: 'App',        data () {            return {                msg: 'hello world'            }        }    }</script>

主要讲解组件普通元素的不同之处,主要有2点:

如何生成VNode&mdash;&mdash;创建组件VNodecreateComponent

Vue响应式流程及原理是什么

如何patch&mdash;&mdash;组件new Vue到patch流程createComponent

$vnode:占位符vnode。最终渲染vnode挂载的地方。所有的组件通过递归调用createComponent直至不再存在组件VNode,最终都会转化成普通的dom。

{    tag: 'vue-component-1-App',    componentInstance: {组件实例},    componentOptions: {Ctor, ..., }}

_vnode:渲染vnode。

{    tag: 'div',    {        "attrs": {            "id": "app"        }    },    // 对应占位符vnode: $vnode    parent: {        tag: 'vue-component-1-App',        componentInstance: {组件实例},        componentOptions: {Ctor, ..., }    },    children: [        // 对应p标签        {             tag: 'p',            // 对应p标签内的文本节点{{ msg }}            children: [{ text: 'hello world' }]        }, {          // 如果还有组件VNode其实也是一样的          tag: 'vue-component-2-xxx'        }                  ]}
  • (注意:这一步对应上图render流程的紫色块的展开!!!)

  • 区分普通元素VNode

    • 普通VNode:tag是html的保留标签,如tag: 'div'

    • 组件VNode:tag是以vue-component开头,如tag: 'vue-component-1-App'

  • (注意:这一步对应上图patch流程的紫色块的展开!!!)

Vue响应式流程及原理是什么

4. Vue组件化简化流程

相信你看完细粒度的Vue组件化过程可能已经晕头转向了,这里会用一个简化版的流程图进行回顾,加深理解

Vue响应式流程及原理是什么

二、响应式流程

案例代码

// 案例export default {    name: 'App',    data () {        return {            msg: 'hello world',            arr = [1, 2, 3]        }    }}

1. 依赖收集

这里会从Observer、Dep、Watcher三个对象进行讲解,分 objectarray 两种依赖收集方式。

  • 一定要注意!数组 的依赖收集 跟 对象的属性 是不一样的。对象属性经过深度遍历后,最终就是以一个基本类型的数据为单位收集依赖,但是数组仍然是一个引用类型

  • 如果这里不懂,先想一个问题: 我们用 this.msg = 'xxx' 能触发 setter 派发更新,但是我们修改数组并不是用 this.arr = xxx ,而是用 this.arr.push(xxx) 等修改数组的方法。很显然,这时候并不是通过触发 arr 的 setter 去派发更新的。那是怎么做的呢?先带着这个问题继续往下看吧!

三个核心对象:Observer(蓝)、Dep(绿)、Watcher(紫)

Vue响应式流程及原理是什么

依赖收集准备阶段&mdash;&mdash;Observer、Dep的实例化

// 以下是initData调用的方法讲解,排列遵循调用顺序function observe (value, asRootData) {  if (!isObject(value)) return // 非对象则不处理  // 实例化Observer对象  var ob;  ob = new Observer(value);  return ob}function Observer (value) {  this.value = value; // 保存当前的data  this.dep = new Dep(); // 实例化dep,数组进行依赖收集的dep(对应案例中的arr)  def(value, '__ob__', this);      if (Array.isArray(value)) {    if (hasProto) {      // 这里会改写数组原型。__proto__指向重写数组方法的对象      protoAugment(value, arrayMethods);     } else {      copyAugment(value, arrayMethods, arrayKeys);    }    this.observeArray(value);  } else {    this.walk(value);   }}// 遍历数组元素,执行对每一项调用observe,也就是说数组中有对象会转成响应式对象Observer.prototype.observeArray = function observeArray (items) {  for (var i = 0, l = items.length; i < l; i++) {    observe(items[i]);  }}// 遍历对象的全部属性,调用defineReactiveObserver.prototype.walk = function walk (obj) {  var keys = Object.keys(obj);  // 如案例代码,这里的 keys = ['msg', 'arr']  for (var i = 0; i < keys.length; i++) {            defineReactive(obj, keys[i]);  }}
function defineReactive (obj, key, val) {  // 产生一个闭包dep  var dep = new Dep();  // 如果val是object类型,递归调用observe,案例代码中的arr会走这个逻辑  var childOb = !shallow && observe(val);  Object.defineProperty(obj, key, {        get: function reactiveGetter () {       // 求value的值      var value = getter ? getter.call(obj) : val;      if (Dep.target) { // Dep.target就是当前的Watcher        // 这里是闭包dep        dep.depend();        if (childOb) {          // 案例代码中arr会走到这个逻辑          childOb.dep.depend(); // 这里是Observer里的dep,数组arr在此依赖收集          if (Array.isArray(value)) {            dependArray(value);          }        }      }      return value    },    set: function reactiveSetter (newVal) {      // 下文派发更新里进行讲解    }  });}
  • 注意 对象 、 数组 的不同处理方式。这里以 核心代码 + 图 进行讲解

  • 接下来核心分析 defineReactive 做了什么。注意 childOb ,这是数组进行依赖收集的地方(也就是为什么我们 this.arr.push(4) 能找到 Watcher 进行派发更新)

Vue响应式流程及原理是什么

依赖收集触发阶段&mdash;&mdash;Wather实例化、访问数据、触发依赖收集

// new Wathcer核心function Watcher (vm, expOrFn, cb, options, isRenderWatcher) {  if (typeof expOrFn === 'function') {  // 渲染watcher中,这里传入的expOrFn是updateComponent = vm.update(vm.render())  // this.getter等价于vm.update(vm.render())    this.getter = expOrFn;   } else {    ...  }  // 这里进行判断,lazy为true时(计算属性)则什么都不执行,否则执行get  this.value = this.lazy    ? undefined    : this.get(); // 本次为渲染Watcher,执行get,继续往下看~}// Watcher的get方法Watcher.prototype.get = function get () {  // 这里很关键,pushTarget就是把当前的Wather赋值给“Dep.target”  pushTarget(this);  var value;  var vm = this.vm;  try {    // 1. 这里调用getter,也就是执行vm.update(vm.render())    // 2. 执行vm.render函数就会访问到响应式数据,触发get进行依赖收集    // 3. 此时的Dep.target为当前的渲染Watcher,数据就可以理所应当的把Watcher加入自己的subs中    // 4. 所以此时,Watcher就能监测到数据变化,实现响应式    value = this.getter.call(vm, vm);  } catch (e) {    ...  } finally {    popTarget();        this.cleanupDeps();   }  return value}
  • Dep.target相关讲解

    • targetStack:栈结构,用来保存Watcher

    • pushTarget:往targetStackpush当前的Watcher(排在前一个Watcher的后面),并把Dep.target赋值给当前Watcher

    • popTargettargetStack最后一个元素弹出(.pop),Dep.target赋值给最后一个Watcher(也就是还原了前一个Watcher)

    • 通过上述实现,vue保证了全局唯一的Watcher,准确赋值在Dep.target

Vue响应式流程及原理是什么

细节太多绕晕了?来个整体流程,从宏观角度再过一遍(computed部分可看完彩蛋后再回来重温一下)

Vue响应式流程及原理是什么

2. 派发更新

派发更新区分对象属性、数组方法进行讲解

如果想要深入了解组件的异步更新,戳这里,了解Vue组件异步更新之nextTick。本文只针对派发更新流程,不会对异步更新DOM进行展开讲解~

这里可以先想一下,以下操作会发生什么?

  • this.msg = 'new val'

  • this.arr.push(4)

是的,毫无疑问都会先触发他们之中的get,那再触发什么呢?我们接下来看

对象属性修改触发set,派发更新。this.msg = 'new val'

...Object.defineProperty (obj, key, {    get () {...},    set: function reactiveSetter (newVal) {      var value = getter ? getter.call(obj) : val;      // 判断新值相比旧值是否已经改变      if (newVal === value || (newVal !== newVal && value !== value)) {        return      }      // 如果新值是引用类型,则将其转化为响应式      childOb = !shallow && observe(newVal);      // 这里通知dep的所有watcher进行更新      dep.notify();    }}        ...

Vue响应式流程及原理是什么

数组调用方法。this.arr.push(4)

// 数组方法改写是在 Observer 方法中function Observer () {    if (hasProto) {         // 用案例讲解,也就是this.arr.__proto__ = arrayMethods        protoAugment(value, arrayMethods);     }}   // 以下是数组方法重写的实现var arrayProto = Array.prototype; // 保存真实数组的原型var arrayMethods = Object.create(arrayProto); // 以真数组为原型创建对象// 可以看成:arrayMethods.__proto__ = Array.prototypevar methodsToPatch = [  'push',  'pop',  'shift',  'unshift',  'splice',  'sort',  'reverse'];// 一个装饰器模型,重写7个数组方法methodsToPatch.forEach(function (method) {  // 保存原生的数组方法  var original = arrayProto[method];  // 劫持arrayMethods对象中的数组方法  def(arrayMethods, method, function mutator () {    var args = [], len = arguments.length;    while ( len-- ) args[ len ] = arguments[ len ];    var result = original.apply(this, args);    var ob = this.__ob__; // 当我门调用this.arr.push(),这里就能到数组对象的ob实例    var inserted;    switch (method) {      case 'push':      case 'unshift':        inserted = args;        break      case 'splice':        inserted = args.slice(2);        break    }    if (inserted) { ob.observeArray(inserted); }    // 由于数组对象在new Observer中实例化了一个dep,并通过childOb逻辑收集了依赖,这里就能在ob实例中拿到dep属性    ob.dep.notify();    return result  });})
  • 这里可以联合数组的依赖收集再看一遍,你就恍然大悟了。为什么 对象的属性 、数组 的依赖收集方式不一样

Vue响应式流程及原理是什么

整个new Vue阶段、到依赖收集派发更新的全部流程就到这里结束了。可以纵观流程图看出,Vue应用就是一个个Vue组件组成的,虽然整个组件化、响应式流程很多,但核心的路径一旦走通,你就会恍然大悟。

三、彩蛋篇

1. computed依赖收集

  • 案例代码

<template>    <div id="app">        {{ name }}    </div></template><script>export default {    name: 'App',    computed: {      name () {        return this.firstName + this.secondName      }    },    data () {        return {            firstName: 'jing',            secondName: 'boran'        }    }}</script>
  • 我们先看流程图。图有点大~大家可以放大看看,每个核心步骤都附有文字说明

Vue响应式流程及原理是什么

根据案例概括一下,加深理解

// 访问computed时触发get的核心代码 function createComputedGetter (key) {  return function computedGetter () {    var watcher = this._computedWatchers && this._computedWatchers[key];    if (watcher) {      if (watcher.dirty) { // dirty第一次为true        watcher.evaluate(); // 这里是对computed进行求值,对computed watcher执行依赖收集      }      if (Dep.target) {        watcher.depend(); // 这里是对渲染Watcher进行依赖收集      }      return watcher.value    }  }}

computed中的name其实就是一个computed Watcher,这个Watcher在init阶段生成

当App组件render的阶段,render函数会访问到模版中的{{ name }},则会触发computed的求值,也就是执行上面代码computedGetter()。执行watcher.evaluate()。也就是执行wathcer.get。上文依赖收集的第3点:依赖收集触发阶段有对get方法进行讲解,忘了的可以上去回顾一下执行watcher.depend()

Watcher.prototype.depend = function depend () {  var i = this.deps.length;  while (i--) {    // 也就是调用Dep.depend => Watcher.addDep => dep.addSub    this.deps[i].depend();   }}
// this.firstName和this.secondName的dep.subsdep.subs: [name的computed watcher, App组件的渲染Watcher]

代码中判断watcher.dirty标志是什么?有什么用?

只有computed的值发生改变(也就是其依赖的数据改变),watcher.dirty才会被设为true

只有watcher.dirtytrue才会对computed进行 求值 或 重新求值

总结:也就是组件每次render,如果computed的值没改变,直接返回value值(是不需要重新计算的),这也是computed的一个特点

  • 首先pushTargetDep.target从App组件的渲染Watcher改为namecomputed Watcher

  • 其次执行cb:function() { return this.firstName + this.secondName }

  • 执行cb的过程中,必然会访问到firstNamesecondName,这时候就是我们熟悉的依赖收集阶段了。firstName、secondName都会把name这个computed watcher收集到自己的dep.subs[]

  • 最后popTarget把name的computed Watcher弹出栈,并恢复Dep.target为当前App组件的渲染Watcher

  • 遍历computed watcher的deps。其实就是firstName、secondName实例的Dep

  • dep.depend也就是调用watcher.addDep(把Dep收集进watcher.deps中),再由watcher.appDep调用dep.addSub(把Watcher收集进dep.subs中)

  • 这样一来,就完成了firstName、secondName对App组件的渲染watcher进行收集

  • 结果如下。响应式数据中会存在两个Watcher

  • 至于为什么响应式数据要收集2个watcher?下文computed派发更新会讲解

讲到这里,我以自己的理解讲解下文章开头引言的问题:为什么Watcher、Dep多对多且相互收集? 这可能也是大家阅读Vue源码中一直存在的一个疑惑(包括我自己刚开始读也是这样)

对的,当然是为了computed中的响应式数据收集渲染Watcher啦!!!

还有!!! 还记得前文中依赖收集的第3点&mdash;&mdash;依赖收集触发阶段的代码讲解中我写了很多注释的cleanupDeps吗?

// 此时flag为true,也就是说msg2没有渲染在页面中<div v-if="flag">{{ msg1 }}</div><div v-else>{{ msg2 }}</div><button @click=() => { this.msg2 = 'change' }>changeMsg2</button>
function cleanupDeps () {  var i = this.deps.length;  while (i--) {    // 这里对watcher所观测的响应式数据的dep进行遍历    // 对的,这样一来,是不是watcher中的deps就发挥作用了呢?    var dep = this.deps[i];    if (!this.newDepIds.has(dep.id)) {      // 这里对当前渲染中没有访问到的响应式数据进行依赖移除      dep.removeSub(this);     }  }  ...}
  • cleanupDeps的作用就是清除掉当前没有使用到的响应式数据。怎么清除?我们往下看

  • 首先看个案例回答个问题,代码如下。当flag为true时,msg2并没有渲染在页面中,那么此时我们点击按钮修改msg2的值会不会、或者应不应该触发这个组件的重新渲染呢?

  • 答案肯定是不会、不应该。所以:cleanupDeps就是为此而存在的

  • cleanupDeps是怎么工作的呢?接着看下面代码

  • 到此,你是否已经懂得了watcher中为什么要收集自己观测的响应式数据对应的dep呢?

2. computed派发更新

派发相对来说比较简单了~跟响应式的派发更新基本一致,继续以案例来讲解吧!

当我们修改firstName会发生什么?this.firstName = 'change'

首先触发firstName的set,最终会调用dep.notify()。firstName的dep.subs中有2个watcher,分别执行对应watcher的notify

Watcher.prototype.update = function update () {        if (this.lazy) {    this.dirty = true; // computed会走到这里,然后就结束了  } else if (this.sync) {    this.run();  } else {    queueWatcher(this); // 渲染watcher会走到这里  }}

computed watcher:将dirty属性置为true。

渲染watcher会执行派发更新流程(如本文响应式流程&mdash;&mdash;2.派发更新一致)

nextTick阶段执行flushSchedulerQueue,则会执行watcher.run()

watcher.run会执行watcher.get方法,也就是重新执行render、update的流程

执行render又会访问到name的computed,从而又会执行computedGetter

此时的watcher.dirty在本步骤3已经置为true,又会执行watcher.evaluate()进行computed的求值,执行watcher.depend()......后续的流程就是派发更新的流程了~

3. user Watcher依赖收集

user Watcher的依赖收集相比computed会简单一点,这里不会赘述太多,只说核心区别,还有watch的常用配置immediatedeepsync

user Watcher在init阶段会执行一次watcher.get(),在这里会访问我们watch的响应式数据,从而进行依赖收集。回顾下computed,computed在这个阶段什么也没做。

// 没错,又是这段熟悉的代码this.value = this.lazy  ? undefined  : this.get(); // user Watcher和渲染 Watcher都在new Watcher阶段执行get()

如果userWatcher设置的immediate: true,则会在new Watcher后主动触发一次cb的执行

Vue.prototype.$watch = function (expOrFn, cb, options) {  ...  var watcher = new Watcher(vm, expOrFn, cb, options);  if (options.immediate) {    // immediate则会执行我们传入的callback    try {      cb.call(vm, watcher.value);    } catch (error) {          }  }  return function unwatchFn () {    watcher.teardown();  }};

deep逻辑很简单,大概讲下:深度遍历这个对象,访问到该对象的所有属性,以此来触发所有属性的getter。这样,所有属性都会把当前的user Watcher收集到自己的dep中。因此,深层的属性值修改(触发set派发更新能通知到user Watcher),watch自然就能监测到数据改变~感兴趣的同学可以自己去看看源码中traverse的实现。

sync。当前tick执行,以此能先于渲染Wathcer执行。不设置同步的watcher都会放到nextTick中执行。

Watcher.prototype.update = function update () {  if (this.lazy) {    this.dirty = true; // 计算属性  } else if (this.sync) {    this.run(); // 同步的user Wathcer  } else {    queueWatcher(this); // 普通user Watcher和渲染Watcher  }}

Vue响应式流程及原理是什么

读到这里,这篇“Vue响应式流程及原理是什么”文章已经介绍完毕,想要掌握这篇文章的知识点还需要大家自己动手实践使用过才能领会,如果想了解更多相关内容的文章,欢迎关注编程网行业资讯频道。

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

Vue响应式流程及原理是什么

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

Vue响应式流程及原理是什么

本文小编为大家详细介绍“Vue响应式流程及原理是什么”,内容详细,步骤清晰,细节处理妥当,希望这篇“Vue响应式流程及原理是什么”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。一、组件化流程1. 整个new Vue
2023-07-02

vue响应式原理是什么

Vue 的响应式原理是通过数据劫持(Object.defineProperty)实现的,其核心思想是将数据模型和视图模型进行双向绑定,即当数据模型的数据发生变化时,视图模型会自动更新,反之亦然。具体实现方式为,当 Vue 实例化时,Vue
2023-05-13

Vue中响应式原理是什么

这篇文章主要介绍“Vue中响应式原理是什么”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“Vue中响应式原理是什么”文章能帮助大家解决问题。响应式在日常开发中的应用是很常见的,这里举个简单的例子:le
2023-07-05

Vue的响应式原理是什么

本篇内容介绍了“Vue的响应式原理是什么”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!Depvar Dep = function Dep()
2023-06-20

Vue数据响应式原理是什么

本文小编为大家详细介绍“Vue数据响应式原理是什么”,内容详细,步骤清晰,细节处理妥当,希望这篇“Vue数据响应式原理是什么”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。响应式是什么简而言之就是数据变页面变如何实
2023-06-30

Vue中响应式系统实现原理是什么

本篇内容介绍了“Vue中响应式系统实现原理是什么”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!框架每个组件实例都会对应一个watcher实例
2023-07-05

Vue3的响应式原理是什么

ProxyVue3的响应式原理依赖了Proxy这个核心API,通过Proxy可以劫持对象的某些操作。constobj={a:1};constp=newProxy(obj,{get(target,property,receiver){console.log("get");returnReflect.get(target,property,receiver);},set(target,property,value,receiver){console.log("set&q
2023-05-24

Vue3 Reactive响应式原理是什么

一、怎么实现变量变化怎么实现变量变化,相关依赖的结果也跟着变化当原本price=5变为price=20后total应该变为40,但是实际total并不会改变。解决办法可以这样,当变量改变了,重新计算一次,那么结果就会改变为最新的结果。如果需要重新计算,我们需要将total语句存储为一个函数,才能实现依赖的变量改变就进行一次依赖项计算。这里就用effect表示函数名。来,试一下:实现了变量price改变,依赖变量pricequantity的变量total也发生改变。下一步,我们要解决的问题是:应该
2023-05-21

vue3.0响应式函数原理是什么

这篇文章将为大家详细讲解有关vue3.0响应式函数原理是什么,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。前言:Vue3重写了响应式系统,和Vue2相比底层采用Proxy对象实现,在初始化的时候不需要遍历
2023-06-29

Vue2/Vue3的响应式原理是什么

本篇内容主要讲解“Vue2/Vue3的响应式原理是什么”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Vue2/Vue3的响应式原理是什么”吧!在讲解之前,我们先了解一下数据响应式是什么?所谓数据
2023-07-05

深入理解Vue响应式原理及其实现方式

Vue的响应式原理是Vue最核心的特性之一,也是Vue能够为开发者提供高效便捷的开发体验的重要原因之一,这篇文章主要介绍了响应式的原理及其实现方式,需要详细了解可以参考下文
2023-05-19

vue2.0/3.0中响应式的原理是什么

本篇文章为大家展示了vue2.0/3.0中响应式的原理是什么,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。vue是什么Vue是一套用于构建用户界面的渐进式JavaScript框架,Vue与其它大型框
2023-06-15

ssh框架原理及流程是什么

SSH(Struts2+Spring+Hibernate)框架的项目,该架构主要分为三个层次:(1)Struts2:负责web层(2)Spring:业务层的管理(3)Hibernate:负责数据持久化Struts2工作原理:1.初始化一个指向servlet容器
ssh框架原理及流程是什么
2018-08-18

mybatis工作原理及流程是什么

MyBatis是一种持久层框架,它的工作原理及流程如下:1. 配置文件加载:MyBatis首先读取配置文件(通常是mybatis-config.xml),该文件包含了数据库连接信息、映射文件路径等配置。2. 映射文件加载:MyBatis根据
2023-08-14

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录