Vue初体验之MVC和MVVM

Vue初体验之MVC和MVVM

​ 我们都知道Vue是一个构建数据驱动渐进式框架,渐进式的意思就是在开发过程中根据需要引入三方包,不断完善项目。数据驱动就是数据发生改变,页面自动刷新,也就是数据的双向绑定,响应式。这也是Vue最大的特性和优点之一

​ 那么实现响应式的原理到底是什么呢?本文主要就是概述一下Vue响应式(数据双向绑定)的原理

Vue响应式原理概述(个人见解):

主要是利用了MVVM架构的思想,使用Object.property()数据劫持结合订阅者发布者模式,给Vue中所有的数据添加了get和set方法,视图想要拿数据必须走get方法,拿的是get中的返回值。当数据更新后会自动触发set方法,每个组件实例都对应一个 watcher 实例,它会在组件渲染的过程中把“接触”过的数据 property 记录为依赖。之后当依赖项的 setter 触发时,会通知 watcher,从而使它关联的组件重新渲染。

一、MVC架构思想

上述原理已经说到,Vue响应式原理是基于MVVM架构的思想实现的,但是MVVM又是由MVC衍生而来,所以在此先简述一下MVC的架构思想。

核心思想:代码层次分明,能够清晰明了分离 数据定义层Model ,渲染视图层View,业务逻辑控制层controller

特点:前端的MVC架构并不能简化代码,只是让代码看起来更具有规范性。

在这里插入图片描述

MVC最简代码实现
<body>
    <div class="box"></div>

    <script>
        // model:数据模型层,提供数据
        const data = {
            uname: '亚洲舞王赵四'
        }

        // view视图层,渲染页面
        function render(){
            document.querySelector('.box').innerHTML = `<h3 οnclick='changeUname()'>${data.uname}</h3>`
        }
        render();

        // controller:控制器层,负责交互行为,修改数据,通知视图层重新渲染页面
        function changeUname(){
            data.uname = '象牙山小诸葛刘能';
            render();
        }

    </script>
</body>

二、MVVM架构思想

模型层(Model): 负责提供数据

视图层(View): 负责渲染页面

视图模型层(ViewModel):连接模型层和视图层的桥梁

特点: 视图更新 通知 defineProperty 更新数据;数据更新 defineProperty 重新渲染页面

在这里插入图片描述

1、Vue中MVVM的体现

在这里插入图片描述

2、Vue中MVVM底层实现的原理(Object.defineproperty()数据劫持)

js在 Object类提供了一个数据挟持的静态方法 Object.defineProperty()

被挟持的数据 永远不能直接赋值,必须走set 方法

被挟持的数据 获取不到自己的值,获取的是get方法 return 的数据

var data = {
    name:"象牙山小诸葛"
}
//数据挟持,前两个参数分别是要劫持的对象和劫持对象中的属性
Object.defineProperty(data,'name',{
    //获取挟持数据的值时自动触发
    get(){
        console.log('get....');
        return '亚洲舞王';
    },
    //设置 挟持数据的值时自动触发
    set(newVal){
        console.log('set....',newVal); 
    }
})
data.name = '铁锹战神'    //直接赋值失效,把值传给了set方法的newVal 
console.log(data.name);  //获取值 拿不到对象中的数据,拿到的是 get方法 return的数据 ====输出'亚洲舞王'

3、最简MVVM代码实现
// 模型层
let data = {
    uname:'象牙山小诸葛'
}

// 视图模型层
let tempUname = data.uname;
Object.defineProperty(data, 'uname', {
    get(){
        // 访问'uname'时触发的方法
        console.log('get');
        return tempUname;
    },
    set(newVal){
        // 修改'uname'时触发的方法
        console.log('set');
        tempUname = newVal;
        render();
    }
})

// 视图层
function render(){
    document.querySelector('#app').innerHTML = `<h3>${data.uname}</h3> <br/> <input type='text' value=${data.uname} οnchange='changeUname(this)' />`
}
render();

function changeUname(inp) {
    console.log(inp.value);
    data.uname = inp.value;
}
4、Vue2.x的坑

上述响应式原理是Vue2.x版本的,这个响应式会有不完美的地方,那就是监听不到对象的新增属性、数组长度以及通过数组下标添加的新元素

vue底层对以下7个方法单独做了新的封装,让通过以下方法修改的数组也可以是响应式的:
push() pop() shift() unshift() splice() sort() reverse()

`解决`:
# 对象的新增属性: 1. this.$set(对象,'属性','值')2. 合并对象:Object.assign({}, 对象, 新增的对象)3. 浅拷贝: {...对象, 属性:值}

# 数组的操作: 1. this.$set(数组, 索引 ,'值'), 2. 七种方法之一
5、Vue3.x的响应式原理

Vue3.x底层利用了Es6的新特性Proxy构造函数来实现数据的响应式,通过Proxy来代理整个数据对象,解决了Vue2.x版本响应式的缺陷

Proxy简易代码实现:Proxy是可以监听到对象的新属性和数组新元素的,下面代码没有写,只是让大家知道Proxy也可以实现数据的响应式

// M: 模型层
let data = {
    uname: '刘能'
}
// VM: 视图模型
let vm = new Proxy(data, {
    get(target, key) {
        // target: 监听的对象
        // key: 对象的属性名
        // 访问了属性时触发的方法

        return target[key]
    },
    set(target, key, newVal) {
        // 修改了属性时触发的方法
        console.log('set');
        target[key] = newVal;
        render();
    }
})
// V: 视图层
function render() {
    let app = document.querySelector('#app');
    app.innerHTML = `<h3>${vm.uname}</h3><br/><input οnchange="changeUname(this)" type="text" value= ${vm.uname} />`
}
render();

function changeUname(input) {
    vm.uname = input.value;
}
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值