专业IT网络知识平台,分享IT百科知识、生活百科知识解答!

易企推科技
易企推科技

MVVM是什么,MVVM详细介绍

来源:小易整编  作者:小易  发布时间:2023-03-23 04:08
摘要:MVVM是什么,MVVM详细介绍MVVM是Model-View-ViewModel的简写。它本质上就是MVC的改进版。他也是用来开发web应用程序,他把应用程序分成三个部分M:model应用的核心(数据)V:view应用的界面VM:view...

MVVM是什么,MVVM详细介绍

MVVM是什么,MVVM详细介绍

MVVM是Model-View-ViewModel的简写。它本质上就是MVC 的改进版。他也是用来开发web应用程序,他把应用程序分成三个部分

  • M: model 应用的核心(数据)

  • V: view 应用的界面

  • VM: viewmodel,视图模型。他是整个mvvm的核心,他是一个桥梁,连接M与V,能够做到数据变了、页面自动更新(vue)。

从上面描述可以看到很多vue的影子,vue就是基于此思想实现响应式数据模板的。学习MVVM重点也是学习VM。

VM的实现(ES5版本)

要实现VM,首先从其功能入手:VM作为桥梁,连接视图与模型,然后数据发生变化,页面自动更新。

实现思路:

  • 监听数据发生变化(监听了数据的两个行为)

  • 数据:也就是model对象

  • 行为:model对象下属性的读取与修改

  • 数据一旦发生变化,通知视图更新

VM的具体实现

监听数据发生变化需要使用到es5提供的一个古老的api:Object.defineProperty。

此api的意思是:定义对象的某一个属性,用于监听改属性的读取与修改。 由于此api比较古老,所以使用的过程中会出现死循环等问题,解决方式比较固定。

整体的代码如下

// Mconst model = {    name: '张三',    age: 20, }// VM: 视图模型,作为桥梁连接视图与模型, 数据变化页面自动更新。   // 在没定义name之前保存一份副本let _name = model.nameObject.defineProperty(model, 'name', {    // 读取    get() {        return _name    },    // 修改    set(newVal) {        _name = newVal        // 数据变了,通知视图更新        render()    } })// Vfunction render() {    app[xss_clean] = `        <span>${model.name}</span>        <button onclick="changeName()">改名</button>      `} render()function changeName() {    model.name = '李四'}

vue2响应式数据的缺陷【重点】

由于vue底层是响应式模块是通过Object.defineProperty此api取实现,所以带来了一些问题,问题如下:

  • Object.defineProperty一次只能监听一个属性,

  • 对于对象新增的属性,vue2没法监听到,除非使用set方法,详情见一节

  • vue2会深度遍历data下的对象,重写每一个属性的getter、setter,即使这个属性最终不再页面上使用。造成性能你浪费!

vue2响应式数据修改的注意事项 【重要】

有些情况下,数据发生变化,页面也不会更新。官方说明:
https://v2.cn.vuejs.org/v2/guide/reactivity.html

  • 对于对象:新增属性与删除属性监听不到,

  • 使用set(给vue的对象添加一个响应式的属性)可以解决,语法如下:

  • this.$set(对象, 属性名, 值)

  • 对于数组

  • 通过索引直接修改这一整项, 解决方式: this.$set(数组, 索引, 值)

  • 为什么不能通过索引修改数组:数组的长度不固定,也许会上百上千,开销就非常大,所以vue根本没有重写数组索引的get和set.r如果你要自己重写,代码如下,看一参考着理解

```js // 你可以把数组的索引看成对象的键名, 数组的值,看成键值。 也就是arr看成arrObj这个形式 let arr = ['a', 'b', 'c'] let arrObj = { 0: 'a', 1: 'b', 2: 'c' } // 重写索引. 如果数组很长,会很消耗性能 for(let i in arr) { Object.defineProperty(arr, i, { get(){}, set(){} }) } ```

  • 改变数组的长度,也不行

搭建一个cnd的vue2开发环境进行测试

<!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">    <!-- 使用vue的指令 使用vue的数据 -->    {{ user }}    <button @click="changeName">改名</button>    <div>      {{ arr }}      <button @click="changeArr">改arr</button>    </div>    <div>      {{ arrObj }}      <button @click="changeArrObj">改变数组对象中的某一项</button>    </div>  </div>  <script src="https://cdn.jsdelivr.net/npm/vue@2.7.10/dist/vue.js"></script>  <script>    new Vue({      el: '#app',      data: {        user: {          name: '张三',          age: 24,        },        arr: ['张三', '李四', '王五'],        arrObj: [          {name: 'xxx1', age: 24},          {name: 'xxx2', age: 25},          {name: 'xxx3', age: 26},        ]      },      methods: {        changeArrObj() {          console.log(this.arrObj)          // 通过索引改了数组          this.arrObj[0] = '坤坤'        },        changeName() {          // this.user.name = '李四'          // 新增的属性没有getter、setter,所以不是一个响应式数据,所以sex怎么变,页面都不会更新          // this.user.sex = '男'          // Vue.set: 构造函数.方法     ---》 静态方法          // this.$set   实例.方法   ----》 原型上的方法          // 给 user这个对象新增一个响应式的属性sex,初始值为男          this.$set( this.user, 'sex', '男' )          console.log(this.user)        },        // 改变数组        changeArr() {          // 讲数组的第一项换成老王          this.$set(this.arr, 0, '老王')          // this.arr[0] = '老王'          // console.log(this.arr)        },      },      // vue,初始化完数据(使用Object.defineProperty来监听每一个属性)      created() {        console.log(this.user)      },      mounted() {        console.log('mounted')      }    })  </script></body></html>

VM的实现(es6版本)

Proxy的使用

proxy的特点:1. 格局大,代理整个对象。 2. 功能也强大: 能够代理13种行为。3.语法比defineProperty简单了很多。

Proxy 可以理解成,在目标对象之前架设一层“拦截”,外界对该对象的访问,都必须先通过这层拦截。从这个描述来看,Proxy天然的适合做VM这一层代理。其基本语法如下:

// 要被代理的对象const model = {    name: '张三'}// 代理对象(new出来的proxy)const proxy = new Proxy(model, {    // 监听到操作    get(target, key) {        return target[key]    },    set(target, key, newVal) {        // 设置值        target[key] = newVal    } })// 操作(通过代理对象去操作) // 进行修改proxy.name = '李四'// 进行读取proxy.get

具体实现

<div id="app"></div>  <script>    // M    const model = {      name: '张三',      age: 24    }    // VM    let proxy = new Proxy(model, {      get(target, key) {        return target[key]      },      set(target, key, newVal) {        // 改变数据        target[key] = newVal        // 通知视图更新        render()      }    })    // V    function render() {      app[xss_clean] = `        ${proxy.name} - ${proxy.age}        <button onclick="changeName()">改变</button>        <button onclick="changeAge()">改变年龄</button>      `    }    render()    function changeName() {      // 改数据      proxy.name = '李四'    }    function changeAge() {      proxy.age = 40    }  </script>

可以发现使用proxy之后,代码更加简单,对于新增删除属性都能监听到。


本文地址:IT问答频道 https://www.hkm168.com/itwenda/937931.html,易企推百科一个免费的知识分享平台,本站部分文章来网络分享,本着互联网分享的精神,如有涉及到您的权益,请联系我们删除,谢谢!


IT问答
小编:小易整编
相关文章相关阅读
  • 某台微机安装的是64位操作系统中,64位指的是什么

    某台微机安装的是64位操作系统中,64位指的是什么

    某台微机安装的是64位操作系统中,64位指的是cpu的字长,即cpu每次能处理64位二进制数据。字长是cpu的主要技术指标之一,指的是cpu一次能并行处理的二进制位数,字长总是8的整数倍,通常pc机的字长为32位,64位。本教程操作环境:w...

  • 总结CreateJS的详细介绍

    总结CreateJS的详细介绍

    CreateJS库是一款HTML5游戏开发的引擎,是一套可以构建丰富交互体验的HTML5游戏的开源工具包,旨在降低HTML5项目的开发难度和成本,让开发者以熟悉的方式打造更具现代感的网络交互体验。掌握了CreateJS可以更方便的完成HTM...

  • c语言是什么意思

    c语言是什么意思

    一:c语言是什么意思C语言是一门面向过程的、抽象化的通用程序设计语言,广泛应用于底层开发。C语言能以简易的方式编译、处理低级存储器。C语言是仅产生少量的机器语言,以及不需要任何运行环境支持便能运行的高效率程序设计语言。尽管C语言提供了许多低...

  • skype是什么软件

    skype是什么软件

    skype是一种简单的免费软件,使您能够在数分钟之内在世界上的任何角落拨打免费电话,它使用全新的p2p【对等】技术将您与其他skype用户相连接。Skype是一种简单的免费软件,使您能够在数分钟之内在世界上的任何角落拨打免费电话。Sky...

  • 计算机的三类总线分别是什么?

    计算机的三类总线分别是什么?

    计算机的三类总线分别是:控制总线、地址总线和数据总线。控制总线用于将微处理器控制单元的信号,传送到周边设备;地址总线用来指定在ram之中储存的数据的地址;数据总线用于在cpu与ram之间来回传送需要处理或是需要储存的数据。总线(Bus)是计...

  • 2k屏幕是什么意思

    2k屏幕是什么意思

    2k屏幕是指分辨率能够达到2560*1440的屏幕。2k是一个通用术语,指屏幕或者内容的水平分辨率达约2000像素的分辨率等级;又因“16:9”的比例是高清晰度视频规格的国际标准,所以2k分辨率在视频制作、显示屏等领域常见格式为2560*1...

  • mysql中的不等于符号是什么

    mysql中的不等于符号是什么

    mysql中的不等于符号有两种:“!=”和“”;它们都可用于判断数字、字符串、表达式是否不相等。对于“!=”和“”,如果两侧操作数不相等,返回值为1,否则返回值为0;如果两侧操作数有一个是null,那么返回值也是null。本教程操作环境:w...

  • ipad a1822是什么型号

    ipad a1822是什么型号

    ipada1822是苹果ipad第5代的型号;ipad第5代是苹果公司于2017年03月21日在美国加利福尼亚州发布的平板电脑;该机型采用铝镁合金材质一体成型结构;前端外框为白色或黑色;有银色、金色和深空灰色3种外观颜色。本教程操作环境:...

  • 周排行
  • 月排行
  • 年排行

精彩推荐