前端框架通识:MVVM是什么?

MVVM简介 目录 点睛 什么是MVVM 为什么要使用MVVM MVVM的组成部分 点睛 View是视图层,也就是用户界面。前端主要由HTML和CSS来构成,为了更方便地展现ViewModel或者Model层的数据。 Model是指数据模型,泛指后端进行的各种业务逻辑处理和数据操控,主要围绕数据库系统展开。这里的难点主要在于需要和前端约定统一的接口规则。 ViewModel由前端开发人员组织生成和维护的视图数据层。在这一层,前端开发者从后端获取得到Model数据进行转换出来,做二次封装,以生成符合View 阅读详情

可能很多人面试会被问到MVVM是什么?

MVVM 由以下三个内容组成:

  1. view:页面(视图)
  2. model:数据模型(模型)
  3. viewModel:作为桥梁负责沟通view和model(视图模型)

第一阶段(原生阶段),直接用JavaScript操作DOM节点,使用浏览器提供的原生API:

var dom = document.getElementById('name');
dom.innerHTML = 'an';
dom.style.color = 'red';

第二阶段,由于原生API不好用,还要考虑浏览器兼容性,jQuery横空出世,以简洁的API迅速俘获了前端开发者的芳心:

$('#name').text('an').css('color', 'red');

第三阶段,MVC模式,需要服务器端配合,JavaScript可以在前端修改服务器渲染后的数据。

现在,随着前端页面越来越复杂,用户对于交互性要求也越来越高,仅仅用jQuery是远远不够的,所以MVVM模型就应运而生。

第四阶段,MVVM是微软提出,它借鉴了桌面应用程序的MVC思想,在前端页面中,把model用纯javascript对象表示,View负责显示,两者做到了最大限度的分离。把Model和View关联起来的就是ViewModel,ViewModel负责把Model的数据同步到View显示出来,还负责把View的修改同步回Model。

通俗来讲:

在 MVVM 中,UI 是通过数据驱动的,数据一旦改变就会相应的刷新对应的 UI,UI 如果改变,也会改变对应的数据。

这种方式就可以在业务处理中只关心数据的流转,而无需直接和页面打交道。

ViewModel 只关心数据和业务的处理,不关心 View 如何处理数据,在这种情况下,View 和 Model 都可以独立出来,任何一方改变了也不一定需要改变另一方,并且可以将一些可复用的逻辑放在一个 ViewModel 中,让多个 View 复用这个 ViewModel。

在 MVVM 中,最核心的也就是数据双向绑定,例如 Angluar 的脏数据检测,Vue 中的数据劫持。

MVVM框架和jQuery操作DOM相比有什么区别?

jQuery实现修改两个DOM节点的例子:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"> 
<title>菜鸟教程(runoob.com)</title> 
<script src="https://cdn.staticfile.org/jquery/1.10.2/jquery.min.js">
</script>
<script>
$(document).ready(function(){
  $("#name").click(function(){
    var name = 'an-an-s';
	var age = 22;
	$('#name').text(name);
	$('#age').text(age);
  });
});
</script>
</head>
<body>
<p>Hello, <span id="name">an</span>!</p>
<p>You are <span id="age">12</span>.</p>
</body>
</html>

MVVM框架(vue)来实现:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"> 
<title>菜鸟教程(runoob.com)</title> 
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script></script>
</head>
<body>
    <div id="app">
        <p @click="test">Hello, <span id="name">{{userInfo.name}}</span>!</p>
        <p>You are <span id="age">{{userInfo.age}}</span>.</p>
    </div>
</body>
</html>
<script>
    var app = new Vue({
      el: '#app',
      data: {
        userInfo: {
            name: "an", 
            age: 12
        }
      },
      methods: {
          test() {
              this.userInfo.name = "an-an-s"
              this.userInfo.age = 51
          }
      }
    })
    </script>

看代码并运行起来跑了看一下,我们可以得出:

jQuery是直接操作DOM

MVVM(vue)它是操作javascript对象(data里面的userInfo),这就是虚拟DOM(里面做了什么操作在深入vue原理计划讲)

Angluar脏数据检测

当触发了指定事件后会进入脏数据检测,这时会调用 $digest 循环遍历所有的数据观察者,判断当前值是否和先前的值有区别,如果检测到变化的话,会调用 $watch 函数,然后再次调用 $digest 循环直到发现没有变化。循环至少为二次 ,至多为十次。

脏数据检测虽然存在低效的问题,但是不关心数据是通过什么方式改变的,都可以完成任务,但是这在 Vue 中的双向绑定是存在问题的。并且脏数据检测可以实现批量检测出更新的值,再去统一更新 UI,大大减少了操作 DOM 的次数。所以低效也是相对的,这就仁者见仁智者见智了。

Vue数据劫持

Vue 内部使用了 Object.defineProperty() 来实现双向绑定(vue3是使用Proxy),通过这个函数可以监听到 set 和 get 的事件。

Object.difineProperty

Object.defineProperty(obj, prop, descriptor)

obj:要定义属性的对象。
prop:要定义或修改的属性的名称或 Symbol 。
descriptor:要定义或修改的属性描述符。 

入门例子: 

let obj = {
    name: 'an',
    age: 18
}
console.log(obj)
Object.defineProperty(obj, "name", {
    get: function() {
        console.log("get---", name)
        return name
    },
    set: function(newName) {
        console.log("set---",newName, 'age---', this.age)
        name = newName
    }
})
obj.name = "an-an-s"
obj.age = 22

console.log(obj)
console.log(obj.name)

// { name: 'an', age: 18 }
// set--- an-an-s age--- 18
// { name: [Getter/Setter], age: 22 }
// get--- an-an-s
// an-an-s

加深一点的例子:

var data = { name: 'an' }
observe(data)
let name = data.name // -> get value
data.name = 'an-an-a' // -> change value

function observe(obj) {
  // 判断类型
  if (!obj || typeof obj !== 'object') {
    return
  }
  Object.keys(obj).forEach(key => {
    defineReactive(obj, key, obj[key])
  })
}

function defineReactive(obj, key, val) {
  // 递归子属性
  observe(val)
  Object.defineProperty(obj, key, {
    enumerable: true,
    configurable: true,
    get: function reactiveGetter() {
      console.log('get value')
      return val
    },
    set: function reactiveSetter(newVal) {
      console.log('change value')
      val = newVal
    }
  })
}

以上代码简单的实现了如何监听数据的 set 和 get 的事件,但是仅仅如此是不够的,还需要在适当的时候给属性添加发布订阅。

<div>{{name}}</div>

在解析如上模板代码时,遇到 {{name}} 就会给属性 name 添加发布订阅。

// 通过 Dep 解耦
class Dep {
    constructor() {
      this.subs = []
    }
    addSub(sub) {
      // sub 是 Watcher 实例
      this.subs.push(sub)
    }
    notify() {
      this.subs.forEach(sub => {
        sub.update()
      })
    }
}
// 全局属性,通过该属性配置 Watcher
Dep.target = null

function update(value) {
    document.querySelector('div').innerText = value
}

class Watcher {
    constructor(obj, key, cb) {
      // 将 Dep.target 指向自己
      // 然后触发属性的 getter 添加监听
      // 最后将 Dep.target 置空
      Dep.target = this
      this.cb = cb
      this.obj = obj
      this.key = key
      this.value = obj[key]
      Dep.target = null
    }
    update() {
      // 获得新值
      this.value = this.obj[this.key]
      // 调用 update 方法更新 Dom
      this.cb(this.value)
    }
}

function observe(obj) {
    // 判断类型
    if (!obj || typeof obj !== 'object') {
      return
    }
    Object.keys(obj).forEach(key => {
      defineReactive(obj, key, obj[key])
    })
}
  
function defineReactive(obj, key, val) {
    // 递归子属性
    observe(val)

    let dp = new Dep()

    Object.defineProperty(obj, key, {
        enumerable: true,
        configurable: true,
        get: function reactiveGetter() {
            console.log('get value')
            // 将 Watcher 添加到订阅
            if (Dep.target) {
                dp.addSub(Dep.target)
            }
            return val
        },
        set: function reactiveSetter(newVal) {
            console.log('change value')
            val = newVal
            // 执行 watcher 的 update 方法
            dp.notify()
        }
    })
}

var data = { name: 'an' }
observe(data)
// 模拟解析到 `{{name}}` 触发的操作
new Watcher(data, 'name', update)
// update Dom innerText
data.name = 'an'

以上实现了一个简易的双向绑定,核心思路就是手动触发一次属性的 getter 来实现发布订阅的添加。

Proxy

let p = new Proxy(target, handler);

target :需要使用Proxy包装的目标对象(可以是任何类型的对象,包括原生数组,函数,甚至另一个代理)。
handler: 一个对象,其属性是当执行一个操作时定义代理的行为的函数(可以理解为某种触发器)。具体的

入门例子:

let test = {
    name: "an",
    age: 18
};
console.log(test);
test = new Proxy(test, {
    get: function(target, key) {
        console.log('get---', target, key);
        return target[key];
    },
    set: function(target, key, value) {
        console.log('set---', target, key, value);
        return Reflect.set(target, key, value);
    }
});
test.name = "an-an-s";
test.age = 18;
console.log(test);
console.log(test.name);

// { name: 'an', age: 18 }
// set--- { name: 'an', age: 18 } name an-an-s
// set--- { name: 'an-an-s', age: 18 } age 18
// { name: 'an-an-s', age: 18 }
// get--- { name: 'an-an-s', age: 18 } name
// an-an-s

Proxy 与 Object.defineProperty 对比

Object.defineProperty是实现了双向绑定了,但是他还是有缺陷的:

  1. 只能对属性进行数据劫持,所以需要深度遍历整个对象
  2. 对于数组不能监听到数据的变化

虽然 Vue 中确实能检测到数组数据的变化,但是其实是使用了 hack 的办法(覆盖原型方法),并且也是有缺陷的。

const arrayProto = Array.prototype
export const arrayMethods = Object.create(arrayProto)
// hack 以下几个函数
const methodsToPatch = [
  'push',
  'pop',
  'shift',
  'unshift',
  'splice',
  'sort',
  'reverse'
]
methodsToPatch.forEach(function(method) {
  // 获得原生函数
  const original = arrayProto[method]
  def(arrayMethods, method, function mutator(...args) {
    // 调用原生函数
    const result = original.apply(this, args)
    const ob = this.__ob__
    let inserted
    switch (method) {
      case 'push':
      case 'unshift':
        inserted = args
        break
      case 'splice':
        inserted = args.slice(2)
        break
    }
    if (inserted) ob.observeArray(inserted)
    // 触发更新
    ob.dep.notify()
    return result
  })
})

反观 Proxy 就没以上的问题,原生支持监听数组变化,并且可以直接对整个对象进行拦截,所以 Vue 也将在下个大版本中使用 Proxy 替换 Object.defineProperty

let test = [
    {
        name: "an",
        age: 18
    }
]
console.log(test);
test = new Proxy(test, {
    get: function(target, key) {
        console.log('get---', target, key);
        return target[key];
    },
    set: function(target, key, value) {
        console.log('set---', target, key, value);
        return Reflect.set(target, key, value);
    }
});
test[0].name = "an-an-s";
test[0].age = 18;
console.log(test);
console.log(test[0].name);

// [ { name: 'an', age: 18 } ]
// get--- [ { name: 'an', age: 18 } ] 0
// get--- [ { name: 'an-an-s', age: 18 } ] 0
// [ { name: 'an-an-s', age: 18 } ]
// get--- [ { name: 'an-an-s', age: 18 } ] 0
// an-an-s

参考:

https://yuchengkai.cn/docs/frontend/framework.html#mvvm

https://www.liaoxuefeng.com/wiki/1022910821149312/1108898947791072

MVVM框架 在WPF开发中,经典的编程模式是MVVM,是为WPF量身定做的模式,该模式充分利用了WPF的数据绑定机制,最大限度地降低了Xmal文件和CS文件的耦合度,也就是UI显示和逻辑代码的耦合度,如需要更换界面时,逻辑代码修改很少,甚至不用修改。 与WinForm开发相比,我们一般在后置代码中会使用控件的名字来操作控件的属性来更新UI,而在WPF中通常是通过数据绑定来更新UI;在响应用户操作上,WinForm是通过控件的事件来处理,而WPF可以使用命令绑定的方式来处理,耦合度将降低。 一、MVVM框架简介 1. 什 阅读详情

相关推荐

深入理解MVVM架构模式

MVVM是一种用于构建用户界面的软件架构模式,它的名称代表着三个组成部分:Model(模型)、View(视图)和ViewModel(视图模型)。MVVM的主要目标是将应用程序的UI与其底层数据模型分离,通过数据绑定实现数据和UI的自动同步,从而降低代码的耦合度,提高应用程序的可维护性和可测试性。

study_way的博客 2万+

什么是MVVM

1、什么是MVVM MVVM,是Model-View-ViewModel的简写,是M-V-VM三部分组成。它本质上就是MVC 的改进版。MVVM 就是将其中的View 的状态和行为抽象化,其中ViewModel将视图 UI 和业务逻辑分开,它可以取出 Model 的数据同时帮忙处理 View 中由于需要展示内容而涉及的业务逻辑。 MVVM采用双向数据绑定,view中数据变化将自动反映到viewmodel上,反之,model中数据变化也将会自动展示在页面上。把Model和View关联起来的就是ViewM.

春风化雨 8万+

c++实现异步线程池并详细分析线程池析构流程

多线程编程是提高程序性能和响应能力的关键技术之一,异步线程池作为多线程编程的一种有效实现方式,能够管理和复用线程资源,避免频繁创建和销毁线程带来的开销。在本文中,我们将深入探讨如何实现一个异步线程池。

2301_76564925的博客 1598

一、什么是 mvvm? MVC、MVP、MVVM三种模式的区别与详解

MVC、MVP、MVVM都是常见的软件架构模式。MVC(Model-View-Controller)架构模式中,将应用程序分为三个主要部分:模型(Model)、视图(View)和控制器(Controller)。Controller负责处理用户交互和调度业务逻辑,View负责显示数据,Model负责数据的存储和逻辑处理。MVP(Model-View-Presenter)架构模式,类似于MVC,但将View和Model的交互逻辑抽象到了Presenter中。

qq_44849312的博客 1万+

AutoCAD二次开发(.Net)之XData

对于CAD中的实体进行筛选等操作,常常会用到实体的XData属性,下面介绍一下实体的XData的增删改。 //XData的新增,修改跟新增一样,new一个ResultBuffer,赋值即可 Document doc=Application.DocumentManager.MdiActiveDocument; using (DocumentLock dl = doc.LockDocument()) { using (Transaction trans = doc.TransactionManager.S.

qq_21489689的博客 2592

PMP–一、二、三模–分类–13.干系人管理

A:确认是否已制定沟通管理计划,使业务干系人认识到项目的成功之处。B:让业务干系人参加冲刺回顾会议。C:与发起人和关键干系人一起确定产品待办事项列表中的优先要务,以便交付商业利益。D:为关键干系人开展收尾调研。C。

stqer的博客 1418

2024 高级前端面试题之 框架通识 「精选篇」

前端面试题之框架通识「精选篇」

XH_jing的博客 1403

YOLO26优化:AAAI2026 | 融合PartialNet Block的C3k2-YOLO高效目标检测网络 | 轻量化涨点设计

PartialNet Block 结合YOLO26的C3k2模块,进行二次创新。

①答疑群聊服务;②YOLO大模型知识问答系统;③计算机视觉论文生成智能体; 592

Vue.js的通识必修

1、什么是 MVVM? Model–View–ViewModel (MVVM) 是一个软件架构设计模式。MVVM 源自于经典的 Model–View–Controller(MVC)模式 ,MVVM 的出现促进了前端开发与后端业务逻辑的分离,极大地提高了前端开发效率。 MVVM 的核心是 ViewModel 层,它就像是一个中转站(value converter),负责转换 Model 中的数据对象来让数据变得更容易管理和使用,该层向上与视图层进行双向数据绑定,向下与 Model 层通过接口请求进行数据交互

y_xiuzhu的博客 909

四非人的保研之路,2024(2025届)四非计算机的保研经验分享(西南交通、苏大nlp、西电、北邮、山软、山计、电科、厦大等)

本身我就是福建人,xmu 3小时就能到家,然后导这边毕业要求容易,不想读博,达到要求就能放实习,每周打卡35h,比较自由,遂考虑。北邮弱com,联系了蛮多老师,几乎都给了考核机会,面试的老师好几位都考核人工智能基础,会问你卷积的计算,问的还是蛮细的。当时结果是暂定,以为是稳了,遂没联系其他老师,但是之后询问发现只是候补,懒得联系其他老师,928候补到,放弃。东北大学,2000人大机试,入营点送,全国巡回面试,每个人就面不到10分钟,我就被问了3个问题就结束了,候补。科研组,导师有人脉,想读博出成果可以去。

专注于AI领域前沿知识,业余爱好开发软件 4351

【QNX+Android虚拟化方案】129 - USB眼图参数配置

【QNX+Android虚拟化方案】129 - USB眼图参数配置

|~~~热爱生活、努力学习的小伙汁~~~| 821

前端需要理解的 React 知识

组件从概念上类似于 JavaScript 纯函数(多次调用下相同的入参始终返回相同的结果),它接受唯一的入参(即 “props”,包括JSX 所接收的除ref和key之外的属性(attributes)以及子组件(children),props.children 由 JSX 表达式中的子组件组成,而非组件本身定义),无论是使用函数声明还是通过 class 声明,都绝不能修改自身的 props,返回的是用于描述页面展示内容的 React 元素。在 React 组件中,代码重用的主要方式是组合而不是继承。

薛定谔的猫-前端领域 386

springboot&mybatis中数组和字符串数据类型的转换

/前端数组字段//数据库中字段/*与前端交互时使用的get/set*/System.out.println("接收前端数据");/*与前端交互时使用的get/set*//*与数据库交互时使用的get/set*/System.out.println("从数据库中读取数据");/*与数据库交互时使用的get/set*/

l_q_l的专栏 2475

2024年最新【小程序开发之uni-app】通识和实战准备_[uni_modules] 15 14 00,学生会面试有趣的选择题

面试前要精心做好准备,简历上写的知识点和原理都需要准备好,项目上多想想难点和亮点,这是面试时能和别人不一样的地方。还有就是表现出自己的谦虚好学,以及对于未来持续进阶的规划,企业招人更偏爱稳定的人。开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】万事开头难,但是程序员这一条路坚持几年后发展空间还是非常大的,一切重在坚持。为了帮助大家更好更高效的准备面试,特别整理了《前端工程师面试手册》电子稿文件。前端面试题汇总JavaScript性能linux前端资料汇总。

2401_84619467的博客 663

VC中sqlite的使用

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

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

Web前端最新#稳定性-异常上报 前端异常埋点系统初探(1),2024年最新面试心得体会2000字

为了我们每一次构建服务端能拿到最新的map文件,我们编写一个插件让webpack在打包完成后触发一个钩子实现文件上传,在中进行配置调整 webpack 配置resolve: {alias: {},},plugins: [],复制代码/*** 用到了hooks,done表示在打包完成之后* status.compilation.outputOptions就是打包的dist文件*/// 读取目录下的map后缀的文件== null;});

2401_84419493的博客 769

华为的C语言编程规范.pdf

华为技术有限公司内部技术规范。本规范制定了编写C语言程序的基本原则、规则和建议。从代码的清晰、简洁、可测试、安全、程序效率、可移植各个方面对C语言编程作出了具体指导。

前端面试锦集

基本面试: 做过最满意的项目是什么?项目背景?为什么要做这件事情?最终达到什么效果?你处于什么样的角色,起到了什么方面的作用?在项目中遇到什么技术问题?具体是如何解决的? 如果再做这个项目,你会在哪些方面进行改善? 基础扎实: IT行业,哪些发展好的同学都是具备扎实基础知识,如果理解计算机基础会更好,因为我们面临很多非前端计算问题的。 主动思考: 被动完成任务成长会很慢的,需要有自己的想法,而不是仅仅是完成任务的。 自动学习: 前端领域知识淘汰速度很快,需要经常学习新知识。 追溯深度: 遇到问题是多研究背.

Front小思的博客 6724

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

2026毕设ssm+vue教务管理系统论文+程序

本项目基于SSM+Vue框架开发高校选课成绩管理系统,针对传统教务系统在高并发选课、成绩实时折算等方面的不足,构建轻量级解决方案。系统采用前后端分离架构,后端使用SpringBoot整合SSM框架,通过Redis缓存和分布式锁保障选课数据一致性;前端采用Vue3+ElementPlus实现响应式交互。主要功能包括选课冲突检测、成绩权重自定义、多维课表可视化等,支持500并发选课需求。研究重点在于解决高并发场景下的库存超卖问题、成绩折算误差溯源以及跨校区课表冲突提示等痛点,为构建微服务化教务中台提供原型基础。

计算机源码_陈 674

阿里P7Android高级工程师:全网最全-Flutter-与-React-Native-深入对比分析(1)

而对于。

2401_84563875的博客 640

我的博客目录

JavaScript 简介 汇总 变量类型和计算 内置类型 typeof 类型转换 转Boolean 对象转基本类型 四则运算符 ==操作符 比较运算符 原型与原型链 new instanceof 闭包和作用域 执行上下文 this call, apply, bind区别 模拟实现call和appl...

weixin_30701575的博客 103

毕设选题推荐(1)

民族地区文化调研与数字化保护技术研究---青海平弦乐库的建设及播放平台开发。基于HTML5平台的崇左太平古城智慧旅游APP软件设计与实现。基于python爬虫的网上商品比价系统的设计与实现。基于springboot的大学生家教兼职系统。基于WEB的教学质量评价系统的设计与实现。基于springmvc的宠物购买出售系统。基于Android系统的在线学习APP。基于web的客栈公寓民宿的管理 平台。基于python的体育馆场地预约系统。基于MVVM的航班信息webAPP。基于Android的移动数字图书馆。

2401_86117024的博客 225

一篇读懂什么是MVVM?MVVM优缺点?

什么是MVVM?MVVM优缺点?

weixin_48037671的博客 1万+

MVVM风格架构

MVVM是Model-View-ViewModel的简写。它本质上就是MVC的改进版。MVVM就是将其中的View的状态和行为抽象化,让我们将视图UI和业务逻辑分开。当然这些事ViewModel已经帮我们完成了,它可以取出Model的数据同时帮忙处理View中由于需要展示内容而涉及的业务逻辑。微软公司的WPF带来了新的技术体验,如Silverlight、声频、视频、3D、动画……这导致了软件UI层更加细节化、可定制化。

leva的博客 5185

MVVM 和 MVVMLight的关系

一、MVVM 和 MVVMLight介绍 MVVM是Model-View-ViewModel的简写。类似于目前比较流行的MVC、MVP设计模式,主要目的是为了分离视图(View)和模型(Model)的耦合。 它是一种极度优秀的设计模式,但并非框架级别的东西,由MVP(Model-View-Presenter)模式与WPF结合的应用方式时发展演变过来的一种新型架构。 立足于原有MVP框架并且把...

qq_23018459的博客 1206

MVVM架构详解:前端开发的理想选择

在前端开发领域,架构设计始终是一个热门话题。随着应用程序变得越来越复杂,选择合适的架构变得尤为重要。在众多架构模式中,MVVM(Model-View-ViewModel)架构因其独特的优势和广泛的应用受到了开发者的青睐。MVVM架构是MVC(Model-View-Controller)的一种变体,特别适用于数据绑定和视图逻辑处理。这篇文章将详细探讨MVVM架构的各个方面,帮助读者更好地理解和应用这一架构模式。

cooldream2009的博客 7939

MVVM架构

MVVM(Model-View-ViewModel)和MVC、MVP一样,也是一种项目架构模式,目前广泛应用在Android程序设计。MVVM主要由三部分组成,Model数据模型部分,View视图展示部分,ViewModel则是一个特殊的部分,为视图与数据模型的中间件。大概的结构如下图这张图中,将程序分为了若干层。其中,UI控制层包含了我们平时写的Activity、Fragment和布局文件等与界面相关的东西。

云追月的专栏 6240
上一篇: 深入javascript计划八:深入浅出模块化
下一篇: 前端框架通识:路由原理
An_s
博客等级 码龄10年 665粉丝 363原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

打赏作者

An_s

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

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

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

打赏作者

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

抵扣说明:

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

余额充值