热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Vuex和Redux都参照了的Flux模式简单版实现

本文对应老外搞个新东西就喜欢给其取个Cool的名字,什么Flux,Redux,Meteor。本来英语

作者:殷荣桧@腾讯

目录:

1. 为什么需要Flux设计模式

2. Flux设计模式是怎么实现的

本文对应 Github地址 ,如果觉得文章还可以,希望您送上宝贵的Star

老外搞个新东西就喜欢给其取个Cool的名字,什么Flux,Redux,Meteor。本来英语就不是太好的中国人一看就跑路了,What?老子Javascirpt还没学好,你又来这这些。名字都看不懂,还学啥。纷纷感慨:老子学不动了,不要再更新了。其实吧,老外就是把公司的个人档案管理流程应用到了前端数据管理流程中了,然后取了吓跑了很多人的名字Flux而已,不信我给你实现一个 简单版的Flux架构 (代码中对照个人档案管理流程讲解Flux流程),结合下面这张图你再看看是不是。

Vuex和Redux都参照了的Flux模式简单版实现

1.为什么需要Flux设计模式

(1)刀耕火种的年代

最初因为前端就是几个页面和几个js文件,前端对于网站中的全局变量(全局变量就是在哪个页面都可以被访问和修改的变量,如网站的标题)基本上用

window.title = 'XXX'

就可以了。刚上手项目,你全局搜一下window这个关键字也差不多对项目中的全局变量都有个印象了。然后有一天,线上网站中标题出错了(比如:‘爱牛网’ 变成了 ‘屠牛网’),老板一看吓的不轻,让你赶紧看看。你就全局搜一下window.title看一下,原来在D页面title被一个新来的员工改错了(新员工在测试环境下改代码改着玩的,忘删了)。然后你把它修改过来就可以了。

(2)MVC时代

前端发展到中期,应用的场景开始增多,需要一个框架来降低代码的耦合了,Backbone类似的MVC框架出现。通过各个Model来存放数据,包括全局的数据。这个时候全局变量可以通过View(页面)来修改Model中的数据,再反馈到其他的View中去,做到数据同步。这个时期基本上是做一个博客网站,管理系统的体量。

(3) 前端大爆炸时代

前端发展到现在,所应用的场景就越来越多了。有个同学小扎(马克·扎克伯格)在大学里想做个叫Facebook的社交应用,就让前端的朋友帮忙做一做页面。前端同学很快用MVC模式搞定了Facebook前端架构。但是令小扎同学没想到的是,这个叫Facebook的应用火了,功能不停的迭代,增加。前端到同学表示每天加班加点累到只能看着自己手中小扎刚发的1000万美刀的股票骂骂娘。这个时候的前端体量急剧膨胀,上百个View(页面)出现,对应上百个Model(存放前端数据的专用层),经常会出现多个页面对同一个Model数据进行操作,比如有个全局数据刚添加到Model,又来一个页面通知这个全局变量要删除,这个时候其他页面还不知道这个全局变量已经删除了,表示要修改这个数据,再来个页面又要获取这个数据,这个时候就导致前端的数据管理异常的混乱,任何一个页面都有权操作全局变量。你能想象一个公司的员工档案信息中心(类似全局变量)如何任何员工(页面)都可以过来随意的增删改查,你信不信没过几天,你再去档案库查看你的档案,你的学历会变成幼儿园。这个档案信息中心的数据将会一塌糊涂。这就是Facebook有一断时间总是会出现你有未读消息提示,但是你点进去查看却没有任何消息的问题。小扎同学因为这个问题被无数的美国网友骂 What the hell.小扎那叫个火大啊,把前端的主管叫过来一顿痛骂(把美国网友送给他的What the hell都送给了这位主管),让其一个星期内解决此问题(以上骂娘故事纯属虚构,)。这个时候Flux就出现了。这就是为什么需要Flux设计模式。

2.Flux设计模式是怎么实现的

我们直接上代码,在代码中做了非常详细的比喻,再对照文章开始的图,相信你一定能看懂。

(1) Action实现部分

/**
 *(1)Action人事办事大厅(分设:增加档案办事窗口,删除档案办事窗口...)生成器
 *公司员工的档案信息属于重要信息,非HR工作人员不
 *能够直接找档案信息中心的人私自修改自己或他人档案,
 *需要到人事大厅窗口办理,由人事大厅交给人事主管(dispatcher)
 *再由HR人事办事大厅
 */
Action: function Action() {
    return {
        create: function(initData) { // 新建员工办事窗口
            // 办事大厅登记此项事物后由人事主管(dispatcher)通知手下注册过的员工去干(staff_1好像就会干)
            dispatcher.dispatch({ type: 'create', item: initData });
        },
        add: function(item) { // 添加员工办事窗口
            // 办事大厅登记此项事物后由人事主管(dispatcher)通知手下注册过的员工去干(staff_1好像就会干)
            dispatcher.dispatch({ type: 'add', item });
        },
        remove: function(item) { // 删除员工办事窗口
            // 办事大厅登记此项事物后由人事主管(dispatcher)通知手下注册过的员工去干(staff_1好像就会干)
            dispatcher.dispatch({ type: 'remove', item });
        }
    }
},

(2)Dispatcher 实现部分

/**
 * (2)主管生成器
 * 生成各个部门的主管(各种主管,包括hr主管,人事档案主管等)
 */
Dispatcher: function Dispatcher() {
    let _cid = 0; // callbackId
    let _callbacks = [];
    return {
        register: function(callback) {
            _callbacks[_cid] = callback;
            return _cid++;
        },
        unregister: function(_cid) {
            // 从回调数组中删除当前的一项
            _callbacks.splice(_cid, _cid);
        },
        dispatch: function(payload) {
            // 通知所有注册的用户执行回调方法
            _callbacks.forEach(callback => callback(payload));
        }
    }
},		

(3)Store实现部分

/**
 * (3)档案信息中心生成器
 * 所有员工的信息都存放在档案信息中心
 */
Store: function Store() {
    let _itemList = []; // 员工档案信息存放柜
    let _emit = new Flux.Dispatcher(); // 生成档案信息中心主管(姓名_emit)
    // 一个小员工名为staff_1到人事主管dispatcher这注册,这样dispatcher主管就有一个员工啦
    dispatcher.register(function staff_1(payload) {
        // 以下是这个小员工的简历,表明他可以干增加,删除,更新等hr员工该干的活
        switch (payload.type) {
            case 'create': // 创建初始员工(创始人那一批,类似于阿里巴巴的18罗汉之类的)
                _itemList = [...payload.item];
                break;
            case 'add': // 添加一个新的员工档案
                _itemList.push(payload.item);
                break;
            case 'remove': // 删除一个离职员工的档案
                _itemList = _itemList.filter(item => item.id != payload.item.id);
                break;
            default: // 其他操作
                break;
        }
        _emit.dispatch(); // 档案信息中心主管发出通知,让手下注册的员工们开始干活了
    });
    return {
        // 获取员工所有的档案信息
        getList: function() {
            return _itemList;
        },
        // 有新的员工到档案信息中心主管(_emit)这注册报到,这样就有人给主管干活啦
        addEmiter: function(callback) {
            return _emit.register(callback);
        },
        // 干的不爽,从档案信息中心主管这离职了
        removeEmiter: function(callbackId) {
            _emit.unregister(callbackId);
        }
    }
}

(4)最后为页面中的实现部分

// 初始化加载的人员档案列表
var initStaffs = [
    { id: 0, name: '马云' },
    { id: 1, name: '王健林' },
    { id: 2, name: '褚时健' },
];
// 重新把档案信息中心的人事档案渲染到办事大厅大屏幕上
var reRender = function reRender() {
    appEle = document.querySelector('#app');
    ulEle = document.querySelector('#list');
    let allEleArr = [];
    this.store.getList().forEach((item) => {
        allEleArr.push(`
  • ${item.name} 删除
  • `); }); let allStr = allEleArr.join(''); ulEle.innerHTML = allStr; } var remove = function remove(id) { // 整理全离职员工的信息 let delItem = ''; this.store.getList().forEach(item => { if (item.id === id) { delItem = item; } }); // 到人事大厅“删除”办事窗口办理 this.action.remove(delItem); } var add = function add(event) { // 自己整理新员工的档案信息 let itemValue = document.querySelector('#thingInput').value; let currentList = this.store.getList(); let lastId = currentList.length ? currentList[currentList.length - 1].id : 0; let item = { id: lastId + 1, name: itemValue } // 整理好了到人事大厅“添加”办事窗口办理新增员工业务 this.action.add(item); } var dispatcher = new Flux.Dispatcher(); // // 生成一个HR人事主管(主管姓名:dipatcher)(主管员工的增删改查) var store = new Flux.Store(); // 生成一个名为store的档案信息中心 var action = new Flux.Action(); // 生成一个名为action的人事办事大厅 setTimeout(() => { // 将初始员工的信息到人事大厅新建办事窗口办理,以便存放到档案信息中心的档案柜中 action.create(initStaffs); // 档案信息中心主管这来了一个新员工注册了,他的本领都在 reRender 函数中说明了 store.addEmiter(reRender); // 代码加载完毕后,点亮办事大厅的所有员工档案信息展示大屏幕 reRender(); }, 0);

    最后我还是墙裂建议你把我的 代码 clone下来,直接打开其中的index.html就能运行。然后再仔细看看,如果发现有写的不对的地方反手就是一个Issue提给我。最后还是那就不要脸的话,如果你觉的讲的还可以,Please送上你宝贵的Star。


    以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 我们


    推荐阅读
    • 本文介绍了在Vue项目中如何结合Element UI解决连续上传多张图片及图片编辑的问题。作者强调了在编码前要明确需求和所需要的结果,并详细描述了自己的代码实现过程。 ... [详细]
    • XML介绍与使用的概述及标签规则
      本文介绍了XML的基本概念和用途,包括XML的可扩展性和标签的自定义特性。同时还详细解释了XML标签的规则,包括标签的尖括号和合法标识符的组成,标签必须成对出现的原则以及特殊标签的使用方法。通过本文的阅读,读者可以对XML的基本知识有一个全面的了解。 ... [详细]
    • SpringMVC接收请求参数的方式总结
      本文总结了在SpringMVC开发中处理控制器参数的各种方式,包括处理使用@RequestParam注解的参数、MultipartFile类型参数和Simple类型参数的RequestParamMethodArgumentResolver,处理@RequestBody注解的参数的RequestResponseBodyMethodProcessor,以及PathVariableMapMethodArgumentResol等子类。 ... [详细]
    • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
    • 目录实现效果:实现环境实现方法一:基本思路主要代码JavaScript代码总结方法二主要代码总结方法三基本思路主要代码JavaScriptHTML总结实 ... [详细]
    • Mac OS 升级到11.2.2 Eclipse打不开了,报错Failed to create the Java Virtual Machine
      本文介绍了在Mac OS升级到11.2.2版本后,使用Eclipse打开时出现报错Failed to create the Java Virtual Machine的问题,并提供了解决方法。 ... [详细]
    • C语言注释工具及快捷键,删除C语言注释工具的实现思路
      本文介绍了C语言中注释的两种方式以及注释的作用,提供了删除C语言注释的工具实现思路,并分享了C语言中注释的快捷键操作方法。 ... [详细]
    • 本文介绍了如何在给定的有序字符序列中插入新字符,并保持序列的有序性。通过示例代码演示了插入过程,以及插入后的字符序列。 ... [详细]
    • 如何用UE4制作2D游戏文档——计算篇
      篇首语:本文由编程笔记#小编为大家整理,主要介绍了如何用UE4制作2D游戏文档——计算篇相关的知识,希望对你有一定的参考价值。 ... [详细]
    • 本文介绍了Perl的测试框架Test::Base,它是一个数据驱动的测试框架,可以自动进行单元测试,省去手工编写测试程序的麻烦。与Test::More完全兼容,使用方法简单。以plural函数为例,展示了Test::Base的使用方法。 ... [详细]
    • 1,关于死锁的理解死锁,我们可以简单的理解为是两个线程同时使用同一资源,两个线程又得不到相应的资源而造成永无相互等待的情况。 2,模拟死锁背景介绍:我们创建一个朋友 ... [详细]
    • 本文探讨了C语言中指针的应用与价值,指针在C语言中具有灵活性和可变性,通过指针可以操作系统内存和控制外部I/O端口。文章介绍了指针变量和指针的指向变量的含义和用法,以及判断变量数据类型和指向变量或成员变量的类型的方法。还讨论了指针访问数组元素和下标法数组元素的等价关系,以及指针作为函数参数可以改变主调函数变量的值的特点。此外,文章还提到了指针在动态存储分配、链表创建和相关操作中的应用,以及类成员指针与外部变量的区分方法。通过本文的阐述,读者可以更好地理解和应用C语言中的指针。 ... [详细]
    • 标题: ... [详细]
    • 本文介绍了Linux Shell中括号和整数扩展的使用方法,包括命令组、命令替换、初始化数组以及算术表达式和逻辑判断的相关内容。括号中的命令将会在新开的子shell中顺序执行,括号中的变量不能被脚本余下的部分使用。命令替换可以用于将命令的标准输出作为另一个命令的输入。括号中的运算符和表达式符合C语言运算规则,可以用在整数扩展中进行算术计算和逻辑判断。 ... [详细]
    • MySQL中的MVVC多版本并发控制机制的应用及实现
      本文介绍了MySQL中MVCC的应用及实现机制。MVCC是一种提高并发性能的技术,通过对事务内读取的内存进行处理,避免写操作堵塞读操作的并发问题。与其他数据库系统的MVCC实现机制不尽相同,MySQL的MVCC是在undolog中实现的。通过undolog可以找回数据的历史版本,提供给用户读取或在回滚时覆盖数据页上的数据。MySQL的大多数事务型存储引擎都实现了MVCC,但各自的实现机制有所不同。 ... [详细]
    author-avatar
    爷们风生水起妞子_929
    这个家伙很懒,什么也没留下!
    PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
    Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有