这段时间 在工作之余的休息时间,学习了解Vue ,学习Vue的设计思想,通过Vue官网学习Vue的语法,通过Vue前端技术,搭建构建了一个简单的项目,在项目学习完之后,发现Vue是一个很有意思的前端技术,没事就看了源码,第一次看的时候不知道如何下手,就开始在百度,谷歌,两大搜索神器的帮助下,找到了学习的快捷之路。发现了难啃的骨头,才是最有意思的事。

Vue框架到底为我们做了什么?

  • 数据和视图分离,解耦(开放封闭原则)
    1.所有数据和视图不分离的,都会命中开放封闭原则
    2.Vue 数据独立在 data 里面,视图在 template 中
  • 以数据驱动视图,只关心数据变化,dom 操作被封装
    1. 使用原生js是直接通过操作dom来修改视图,例如
    ducument.getElementById('xx').innerHTML="xxx"
    
    1. 以数据驱动视图就是,我们只管修改数据,视图的部分由框架去帮我们修改,符合开放封闭模式.

如何理解 MVVM ?

  • MVC

    1. Model 数据 → View 视图 → Controller 控制器
  • MVVM
    1. MVVM不算是一种创新
    2. 但是其中的 ViewModel 是一种创新
    3. ViewModel 是真正结合前端应用场景的实现
  • 如何理解MVVM
    1. MVVM - Model View ViewModel,数据,视图,视图模型
    2. 三者与 Vue 的对应:view 对应 template,vm 对应 new Vue({…}),model 对应 data
    3. 三者的关系:view 可以通过事件绑定的方式影响 model,model 可以通过数据绑定的形式影响到view,viewModel是把 model 和 view 连起来的连接器
我们来看一下最后我们要达到的效果

我们先来看下我们简单的结构


以上就是我们简单搭建的项目目录结构,有需要了解可以去阅读源码来了解更多,这里就不做过多的展开

我们先来看下我们index.html完整代码

<!DOCTYPE html>
<html><head><meta charset="utf-8" /><title>MiniMVVM 框架demo演示</title><link rel="stylesheet" href="./css/mini-mvvm.css"/>    </head><body><div id="app"><h1>{{title}}</h1><div><span>文本输入框:</span><input type="text" v-model="message"/></div><section><samp>数据显示结果:</samp><hr/><span>{{message}}</span></section></div><script type="text/javascript" src="js/mini-mvvm.js"></script><script>var app=new MiniMVVM({el:'#app',data:{title:'Mini-MVVM demo演示',message:'Hello World ! ! !'}});</script></body>
</html>

大家看到这里有没有发现,我们调用不是Vue 而是我们自己自定义的MiniMVVM,没错。那我们再来看看Vue的用法,帮大家回顾一下

<div id="app">{{ message }}
</div>
var app = new Vue({el: '#app',data: {message: 'Hello Vue!'}
})
Hello Vue!

我们已经成功创建了第一个 Vue 应用!看起来这跟渲染一个字符串模板非常类似,但是 Vue 在背后做了大量工作。现在数据和 DOM 已经被建立了关联,所有东西都是响应式的。我们要怎么确认呢?打开你的浏览器的 JavaScript 控制台 (就在这个页面打开),并修改 app.message 的值,你将看到上例相应地更新。
接下来是我们的函数类

(function () {//初始化类class MiniMVVM {...}//模板编译类class TemplateCompile {...}//数据劫持类,响应式class Observer {...}//观察者class Watcher {...}//发布订阅类 自定义事件class Emitter {...}//存储指令和工具方法let CompileTool = {...};window.MiniMVVM = MiniMVVM;
})();

这是我们mini版的函数类,这里我们只实现了简单的双向数据绑定,目的是为了让大家学习思想,以及理解分析

function initMixin (Vue) {...}function initInternalComponent (vm, options) {...}function resolveConstructorOptions (Ctor) {...}function resolveModifiedOptions (Ctor) {...}function Vue (options) {if (!(this instanceof Vue)) {warn('Vue is a constructor and should be called with the `new` keyword');}this._init(options);}initMixin(Vue);stateMixin(Vue);eventsMixin(Vue);lifecycleMixin(Vue);renderMixin(Vue);/*  */function initUse (Vue) {...}/*  */function initMixin$1 (Vue) {...}/*  */function initExtend (Vue) {

如果让我们光来看Vue.js 就是一万两千行代码,我相信大多数和我一样,看到这么多行代码人已经崩溃了直接就选择了放弃,我们虽然是mini版的,我们也借助vue设计来写我们mini版。
下面我们就来简单的分析下我们这个函数的作用以及用法

//初始化
class MiniMVVM {constructor(options) {this.$el = options.el;this.$data = options.data;//判断是否有模板,如果有模板的话,就执行编译和数据劫持if (this.$el) {//1,数据劫持this.$data = (new Observer()).observe(this.$data);//2,模板编译new TemplateCompile(this.$el, this);}}}

这里我们主要是为了获取我们模板信息以及数据
下一步我们来看一下我们数据劫持监听

 //数据劫持类,响应式class Observer {constructor(data) {this.data = data;this.observe(this.data);}observe(data) {//验证是否存在,是否是对象if (!data || typeof data !== 'object') {return;}//使用proxy 代理拦截监听let that = this;//初始化发布订阅let emitter = new Emitter();let handler = {get(target, key) {//递归当前target[key] 是否是对象if (typeof target[key] === 'object' && target[key] !== null) {return new Proxy(target[key], handler);}//判断当前key下面的watcher是否存在if (Emitter.watcher) {emitter.addSub(Emitter.watcher);}return target[key];},set(target, key, newVal) {if (target[key] !== newVal) {target[key] = newVal;emitter.notify();}}}//创建proxy代理let pdata = new Proxy(data, handler);return pdata;}}

Proxy语法和用例

let p = new Proxy(target, handler);

将目标和处理程序传递给Proxy构造函数,这样就创建了一个proxy对象。

//模板编译类class TemplateCompile {constructor(el, vm) {//1,获取元素this.el = (el.nodeType === 1 ? el : document.querySelector(el));//2,获取vm实例this.vm = vm;//如果元素存在,然后我们进行编译if (this.el) {//获取模板let fragment = this.nodeToFragment(this.el);//模板语法解析this.cpmpile(fragment);//把最后生成的文档结构重新append到我们页面中去this.el.appendChild(fragment);}}//获取模板nodeToFragment(el) {let fragment = document.createDocumentFragment();let firstChild = null;while (firstChild = el.firstChild) {fragment.appendChild(firstChild);}return fragment;}//解析文档碎片,编译模板中的变量cpmpile(fragment) {//1,获取所有的子节点(包括元素解点)let childNodes = fragment.childNodes;//2,遍历循环每个节点Array.from(childNodes).forEach(node => {//如果是元素节点if (node.nodeType === 1) {//递归遍历子节点this.cpmpile(node);//处理我们的元素节点this.complieElement(node);} else {//处理我们的文本节点this.complieText(node);}})}//编译处理complieText(nodeText) {//获取文本节点的内容let exp = nodeText.textContent;//这里我们通过正则获取{{}}里面的数据let re = /{{[^}]+}}/g;if (re.test(exp)) {//渲染页面数据CompileTool.text(nodeText, this.vm, exp)}}//编译处理元素节点complieElement(node) {console.log(node);//取出所有的属性let attrs = node.attributes;//边里属性 检测是否具备‘-v’Array.from(attrs).forEach(attr => {console.log(attr.name);if (attr.name.includes('v-')) {//如果是v-attr 这样的指令 我们去我们对应的寻找属性值字符串所对应的值let exp = attr.value;let type = exp.split('-')[1];//调用model指令对应的方法,渲染页面数据CompileTool.model(node, this.vm, exp);}})}}

这是我们模板类代码,这里主要是解析我们定义好的模板语法,下面我们再来看下我们观察者类

//观察者class Watcher {constructor(vm, exp, callback) {this.vm = vm;this.exp = exp;this.callback = callback;//获取当前的值this.oldValue = this.get();}get() {//初始化发布订阅状态值Emitter.watcher = this;//获取这个data上面的值let val = CompileTool.getVal(this.vm, this.exp)//清空一下发布状态置Emitter.watcher = null;//返回当前值return val;}update() {//获取当前值let newVal = CompileTool.getVal(this.vm, this.exp)//拿到旧的值let oldVal = this.oldValue;//比较两次的值,是否保持一致,如果不一致就执行回调if (newVal != oldVal) {this.callback(newVal);}}}

观察者见名思义,看过或者学习过设计模式的都应该知道观察者模式,这里就不做过多的解释,有兴趣的朋友可以百度一下。
剩下的就是我们的发布订阅

//发布订阅类 自定义事件class Emitter {constructor() {this.subs = [];}//添加一个订阅addSub(watcher) {this.subs.push(watcher);}//通知执行订阅notify() {this.subs.forEach(v => v.update());}}

通过以上不到300的行的代码,我们就实现了简单的双向数据绑定
有朋友会说你现在没有其他的文件以及配置,是的,不需要我们也是能实现数据的双向绑定,这里的剩下的webpack打包,webpack打包这个算是比较简单了,对于学习前端vue来说,那是再熟悉不过的了,这里就不过多的介绍了,下一章节我们在继续探讨webpack打包脚本详细介绍。

下面提供几个学习es地址大家可以去看一下,中英文都有。

ES5地址

中文版:中文地址
英文版:英文地址

ES6地址

中文版:中文地址
英文版:英文地址
ES6的浏览器兼容性问题:地址

非常感谢您能抽出时间来阅读,如果对你有所帮助,欢迎转发分享,您的转发分享就是对我最大的鼓励和支持。

有兴趣的朋友欢迎加入交流!!!

手把手教你Vue从零撸一个迷你版MVVM框架相关推荐

  1. 10分钟手把手教你用Android手撸一个简易的个人记账App

    用Android手撸一个简易的个人记账系统 ⛱️序言

  2. 手把手教你从0开始搭建一个vue项目(完结)

    前言 上一节webpack实战之(手把手教你从0开始搭建一个vue项目)最后我们完成了css样式的配置: webpack.config.js: const path = require("p ...

  3. 还没理解微前端?手把手教你实现一个迷你版

    大厂技术  高级前端  Node进阶 点击上方 程序员成长指北,关注公众号 回复1,加入高级Node交流群 最近看了几个微前端框架的源码(single-spa[1].qiankun[2].micro- ...

  4. 一个精美的跳动小球—手把手教你用贝塞尔曲线实现一个酷炫跳动动画。

    一个精美的跳动小球-手把手教你用贝塞尔曲线实现一个酷炫跳动动画. 2017-08-07 BraveJoy 终端研发部 前言介绍 手把手教你用贝塞尔曲线实现一个精美的跳动的小球. 正文 效果展示: 说点 ...

  5. 手把手教你如何用Python制作一个电子相册?末附python教程

    这里简单介绍一下python制作电子相册的过程,主要用到tkinter和pillow这2个库,tkinter用于窗口显示照片,pillow用来处理照片,照片切换分为2种方式,一种是自动切换(每隔5秒) ...

  6. 手把手教你用苹果CMS做一个电影视频网站 可直接在线播放

    现在大家在网上看电影很方便了,因为电影网站多如牛毛!那很多人在想,做电影网站难么?能否拥有一个属于自己的电影网站呢?其实真的可以,而且很简单下面我们就来手把手的教你如何做一个电影网站!因为我的空间是P ...

  7. 手把手教你把Vim改装成一个IDE编程环境(图文)

    手把手教你把Vim改装成一个IDE编程环境(图文) By: 吴垠 Date: 2007-09-07 Version: 0.5 Email: lazy.fox.wu#gmail.com Homepage ...

  8. Android反编译:手把手教你制作高德地图车机共存版

    Android反编译:手把手教你制作高德地图车机共存版 前言 前期准备 反编译流程 反编译获取有效信息 修改关键信息 修改包名 修改其它配置 生成APK 重新打包成apk 重新签名 绕过校验机制 定位 ...

  9. javascript实现图片轮播_手撸一个简易版轮播图(上)

    手撸一个简易版轮播图 实现原理,通过控制 swiper-warpper 容器的定位来达到切换图片的效果. 页面布局 简易版轮播图 < > 页面样式 .container{width: 60 ...

最新文章

  1. [技术转载]C#知识点集合 (面试必备)
  2. 邀请参加活动的邀请函_邀请函||王坝镇中心幼儿园邀请家长参加期中分享活动的通知...
  3. 内网通 去广告_新高一攻略|让我们一起跟升学e网通名师看看如何学好高中化学...
  4. ThinkPHP3.2 volist嵌套循环显示原理
  5. 时间设置偏移秒_零偏移有源低通滤波器,第2部分
  6. JAVA Stack栈和Heap堆的区别(转)
  7. 《小学生C++趣味编程》第42课 最小公倍数
  8. war 发布后页面不更新_吐槽 | 都发布一万年了,这游戏还不“更新”?
  9. 求给定精度的简单交错序列部分和 (15 分)
  10. jQuery重置表单2
  11. 服务器报告它来自digest_2020年全球服务器市场规模及竞争格局分析
  12. 最常被利用的三大 API 漏洞:是什么、为什么、如何阻止?
  13. 软件开发管理与质量控制
  14. IBM IT 企业基础架构解决方案
  15. python模拟鼠标点击脚本_python模拟鼠标点击和键盘输入的操作
  16. 毕业生签约时必须知道三件事:三方协议、干部身份、派遣证
  17. Jboss部署Springboot项目
  18. win10 系统亮度调节
  19. Linux下的硬件驱动——USB设备
  20. 注塑模设计的一般流程,模具新人必看

热门文章

  1. 计算机应用基础0039答案,计算机应用基础-0039(贵州电大-课程号:5205004)参考资料...
  2. VBox安装xp虚拟机无法上网
  3. 交叉编译cups-2.3.3
  4. 刺激前低的EEG alpha功率增强了视觉知觉,但不是视觉知觉敏感度
  5. python里的map是什么意思_python中map什么意思
  6. 详细解读【虚拟内存】
  7. 7-4 Swan学院社团招新 (20 分)
  8. 【评测】无血清细胞冻存液
  9. 家用计算机的ram怎么清理,计算机内存怎么清理
  10. python实现远程控制