javascript编写_如何通过编写自己的Web开发框架来提高JavaScript技能
javascript编写
Have you ever asked yourself how a framework works?
您是否曾经问过自己框架是如何工作的?
When I discovered AngularJS after learning jQuery many years ago, AngularJS seemed like dark magic to me.
多年前学习jQuery后,当我发现AngularJS时 ,AngularJS在我看来就像是黑魔法。
Then Vue.js came out, and upon analyzing how it works under the hood, I was encouraged to try writing my own two-way binding system.
然后Vue.js出现了,并且在分析了它的幕后工作原理后,我被鼓励尝试编写自己的双向绑定系统 。
In this article, I’ll show you how to write a modern JavaScript framework with custom HTML element attributes, reactivity, and double-binding.
在本文中,我将向您展示如何编写具有自定义HTML元素属性,React性和双重绑定的现代JavaScript框架。
React性如何工作? (How does reactivity work?)
It would be good to start with an understanding of how reactivity works. The good news is that this is simple. Actually, when you declare a new component in Vue.js, the framework will proxify each property (getters and setters) using the proxy design pattern.
最好先了解React性如何工作。 好消息是,这很简单。 实际上,当您在Vue.js中声明一个新组件时,该框架将使用代理设计模式代理 每个属性 (getter和setter)。
Thus it will be able to detect property value changes both from code and user inputs.
因此,它将能够从代码和用户输入中检测属性值的变化。
代理设计模式是什么样的 (What the proxy design pattern looks like)
The idea behind the proxy pattern is simply to overload access to an object. An analogy in real life could be the access to your bank account.
代理模式背后的想法仅仅是使对对象的访问超载。 现实生活中的类比可能是访问您的银行帐户。
For example, you can’t directly access your bank account balance and change the value according to your needs. It is necessary for you to ask someone that has this permission, in this case, your bank.
例如,您不能直接访问您的银行帐户余额并根据需要更改值。 您必须询问具有此权限的人,在这种情况下,是您的银行。
var account = {balance: 5000
}// A bank acts like a proxy between your bank account and you
var bank = new Proxy(account, {get: function (target, prop) {return 9000000;}
});console.log(account.balance); // 5,000 (your real balance)
console.log(bank.balance); // 9,000,000 (the bank is lying)
console.log(bank.currency); // 9,000,000 (the bank is doing anything)
In the example above, when using the bank
object to access the account
balance, the getter function is overloaded, and it always returns 9,000,000
instead of the property value, even if the property doesn’t exist.
在上面的示例中,当使用bank
对象访问account
余额时,getter函数被重载,即使该属性不存在,它也总是返回9,000,000
而不是该属性值。
// Overload setter default function
var bank = new Proxy(account, {set: function (target, prop, value) {// Always set property value to 0return Reflect.set(target, prop, 0); }
});account.balance = 5800;
console.log(account.balance); // 5,800bank.balance = 5400;
console.log(account.balance); // 0 (the bank is doing anything)
By overloading the set
function, it’s possible to manipulate its behavior. You can change the value to set, update another property instead, or even not do anything at all.
通过重载set
函数,可以操纵其行为。 您可以更改该值以进行设置,改为更新另一个属性,甚至完全不执行任何操作。
React性示例 (Reactivity example)
Now that you’re confident about how the proxy design pattern works, let’s begin writting our JavaScript framework.
现在,您对代理设计模式的工作方式很有信心,让我们开始编写我们JavaScript框架。
To keep it simple, we’ll mimic the AngularJS syntax to do it. Declaring a controller and binding template elements to controller properties is quite straightforward.
为了简单起见,我们将模仿AngularJS语法来做到这一点。 声明一个控制器并将模板元素绑定到控制器属性非常简单。
<div ng-controller="InputController"><!-- "Hello World!" --><input ng-bind="message"/> <input ng-bind="message"/>
</div><script type="javascript">function InputController () {this.message = 'Hello World!';}angular.controller('InputController', InputController);
</script>
First, define a controller with properties. Then use this controller in a template. Finally, use the ng-bind
attribute to enable double-binding with the element value.
首先,定义一个带有属性的控制器。 然后在模板中使用此控制器。 最后,使用ng-bind
属性启用与元素值的双重绑定。
解析模板并实例化控制器 (Parse template and instantiate the controller)
To have properties to bind, we need to get a place (aka controller) to declare those properties. Thus, it is necessary to define a controller and introduce it to our framework.
要绑定属性,我们需要一个位置(又称控制器)来声明这些属性。 因此,有必要定义一个控制器并将其引入我们的框架。
During the controller declaration, the framework will look for elements that have ng-controller
attributes.
在控制器声明期间,框架将查找具有ng-controller
属性的元素。
If it fits with one of the declared controllers, it will create a new instance of this controller. This controller instance is only responsible for this particular piece of template.
如果适合声明的控制器之一,它将创建该控制器的新实例。 该控制器实例仅负责此特定模板。
var controllers = {};
var addController = function (name, constructor) {// Store controller constructorcontrollers[name] = {factory: constructor,instances: []};// Look for elements using the controllervar element = document.querySelector('[ng-controller=' + name + ']');if (!element){return; // No element uses this controller}// Create a new instance and save itvar ctrl = new controllers[name].factory;controllers[name].instances.push(ctrl);// Look for bindings.....
};addController('InputController', InputController);
Here is what the handmade controllers
variable declaration looks like. The controllers
object contains all controllers declared within the framework by calling addController
.
这是手工controllers
变量声明的样子。 controllers
对象包含通过调用addController
在框架内声明的所有控制器。
For each controller, a factory
function is saved to instantiate a new controller when needed. The framework also stores each of the new instances of the same controller used in the template.
对于每个控制器,将保存factory
功能以在需要时实例化新控制器。 该框架还存储模板中使用的同一控制器的每个新实例。
寻找绑定 (Looking for bindings)
At this point, we’ve got an instance of the controller and a piece of template using this instance.
至此,我们已经有了一个控制器实例和一个使用该实例的模板。
The next step is to look for elements with bindings which use controller properties.
下一步是寻找具有绑定的元素,这些绑定使用控制器属性。
var bindings = {};// Note: element is the dom element using the controller
Array.prototype.slice.call(element.querySelectorAll('[ng-bind]')).map(function (element) {var boundValue = element.getAttribute('ng-bind');if(!bindings[boundValue]) {bindings[boundValue] = {boundValue: boundValue,elements: []}}bindings[boundValue].elements.push(element);});
Quite simple, it stores all bindings of an object (used as a hash map). This variable contains all the properties to bind with the current value and all DOM elements which bind this property.
非常简单,它存储对象的所有绑定(用作哈希映射 )。 此变量包含所有要与当前值绑定的属性以及所有与该属性绑定的DOM元素。
双绑定控制器属性 (Double bind controller properties)
After the preliminary work has been done by the framework, now comes the interesting part: double-binding.
在框架完成了初步工作之后,现在出现了有趣的部分: double-binding 。
It involves binding the controller property to the DOM elements to update the DOM whenever the code updates the property value.
它涉及将控制器属性绑定到DOM元素以在代码更新属性值时更新DOM。
Also, don’t forget to bind the DOM elements to the controller property. This way, when the user changes the input value, it’ll update the controller property. Then it will also update all other elements bound to this property.
另外,不要忘记将DOM元素绑定到controller属性。 这样,当用户更改输入值时,它将更新控制器属性。 然后,它还将更新绑定到该属性的所有其他元素。
使用代理检测代码更新 (Detect updates from code with a proxy)
As explained above, Vue wraps components within a proxy to react to property changes. Let’s do the same by proxying the setter only for controller bound properties.
如上所述,Vue将组件包装在代理中以对属性更改做出React。 通过仅为控制器绑定的属性代理设置器来进行相同的操作。
// Note: ctrl is the controller instance
var proxy = new Proxy(ctrl, {set: function (target, prop, value) {var bind = bindings[prop];if(bind) {// Update each DOM element bound to the property bind.elements.forEach(function (element) {element.value = value;element.setAttribute('value', value);});}return Reflect.set(target, prop, value);}
});
Whenever a bound property is set, the proxy will check all elements bound to this property. Then it will update them with the new value.
无论何时设置绑定属性,代理都会检查绑定到该属性的所有元素。 然后它将使用新值更新它们。
In this example, we support only input elements binding, because only the value
attribute is set.
在此示例中,我们仅支持输入元素绑定,因为仅设置了value
属性。
对元素事件做出React (React to element events)
The last thing to do is reacting to user interactions. DOM elements trigger events when they detect a value change.
最后要做的是对用户交互做出React。 DOM元素在检测到值更改时触发事件。
Listen to those events and update the bound property with the new value from the event. All other elements bound to the same property will update automatically thanks to the proxy.
侦听那些事件,并使用事件中的新值更新绑定属性。 由于代理,绑定到同一属性的所有其他元素将自动更新。
Object.keys(bindings).forEach(function (boundValue) {var bind = bindings[boundValue];// Listen elements event and update proxy property bind.elements.forEach(function (element) {element.addEventListener('input', function (event) {proxy[bind.boundValue] = event.target.value; // Also triggers the proxy setter});})
});
Once you put everything together, you get handmade double-bound inputs. Here is a working demo including all the code.
将所有内容放到一起后,您将获得手工制作的双向输入。 这是一个包含所有代码的有效演示。
Thank you for reading. I hope it helped you to demystify how JavaScript frameworks work.
感谢您的阅读。 我希望它能帮助您揭开JavaScript框架的神秘面纱。
Congratulations! You’ve developed popular features such as custom HTML element attributes, reactivity, and double-binding!
恭喜你! 您已经开发了流行的功能,例如自定义HTML元素属性,React性和双重绑定!
If you found this article useful, please click on the 👏 button a few times to make others find the article and to show your support! 👊
如果您觉得这篇文章很有用,请单击 几次make按钮,以使其他人找到该文章并表示支持! 👊
Don’t forget to follow me to get notified of my upcoming articles 🙏
不要忘记关注我,以获取有关我即将发表的文章的通知 🙏
查看我的其他帖子 (Check out my Other Posts)
https://www.freecodecamp.org/news/author/jbardon/
https://www.freecodecamp.org/news/author/jbardon/
➥对初学者的React (➥ React for beginners)
A Quick Guide to Learn React and How its Virtual DOM Works
快速了解React及其虚拟DOM的工作原理
How to Bring Reactivity into React with States
如何使React性与国家互动
➥JavaScript (➥ JavaScript)
Common Mistakes to Avoid While Working with Vue.js
使用Vue.js时应避免的常见错误
Stop Painful JavaScript Debug and Embrace Intellij with Source Map
停止痛苦JavaScript调试,并使用Source Map拥抱Intellij
How To Reduce Enormous JavaScript Bundles Without Effort
如何毫不费力地减少JavaScript捆绑包
翻译自: https://www.freecodecamp.org/news/how-to-improve-your-javascript-skills-by-writing-your-own-web-development-framework-eed2226f190/
javascript编写
相关文章:

2016ACM/ICPC亚洲区大连站现场赛题解报告(转)
http://blog.csdn.net/queuelovestack/article/details/53055418 下午重现了一下大连赛区的比赛,感觉有点神奇,重现时居然改了现场赛的数据范围,原本过的人数比较多的题结果重现过的变少了,而原本现场赛全场过的人最少的题重现做出的人反而多了一堆,不过还是不影响最水的6题,然…

微信小程序插件新增能力
微信小程序开发交流qq群 173683895 承接微信小程序开发。扫码加微信。 正文: “ 小程序插件能力升级:开放插件登录能力,帮助插件开发者更好地管理用户;支持在插件内使用微信支付能力,便于用户在插件内完成预订、购…

ubutun:从共享文件夹拷贝文件尽量使用cp命令而不是CTRL+C/V
为了方便,VBOX安装的Ubuntu,并在硬盘上创建了一个与Windows的共享文件夹sharefolder方便在两个系统之间传文件 但是经常发现的问题就是从sharefolder中拷贝文件到ubuntu中会出现很多毛病,比如说经常按了CTRLC之后没有拷贝最新的文件ÿ…

影像锐化工具_如何以及为什么要进行工具改造:花在锐化斧头上的时间永远不会浪费...
影像锐化工具by Harshdeep S Jawanda通过Harshdeep S Jawanda 如何以及为什么要进行工具改造:花在锐化斧头上的时间永远不会浪费 (How and why you should tool-up: time spent sharpening your axe is never wasted) There is this old anecdote about two friend…

ListT随机返回一个
/// <summary> /// 随机返回一条数据 /// </summary> /// <param name"list"></param> /// <returns></returns> protected string GetRandomData(List<string> list) {return list.OrderBy(_ > Guid.NewGuid()).First…
微信小程序插件功能页开发详细流程
有问题可以扫码加我微信,有偿解决问题。承接小程序开发。 微信小程序开发交流qq群 173683895 、 526474645 ; 正文: 关于新出的微信小程序插件功能页做一下记录,希望能帮到大家 步骤: 1.打开开发者工具&#x…

(拆点+最小路径覆盖) bzoj 2150
2150: 部落战争 Time Limit: 10 Sec Memory Limit: 259 MBSubmit: 518 Solved: 298[Submit][Status][Discuss]Description lanzerb的部落在A国的上部,他们不满天寒地冻的环境,于是准备向A国的下部征战来获得更大的领土。 A国是一个M*N的矩阵࿰…

使用Flow检查React,Redux和React-Redux的全面指南
by Fabian Terh由Fabian Terh 使用Flow检查React,Redux和React-Redux的全面指南 (A comprehensive guide to type checking React, Redux, and React-Redux with Flow) This article is divided into 4 sections:本文分为4个部分: Type checking Redux…

微信小程序WebSocket实现聊天对话功能完整源码
相关文章: 1.小程序聊天群,发送语音,文字,图片。 2.微信小程序集成腾讯IM,实现实时音视频通话,1V1聊天 3.云开发微信小程序聊天群 4.接入网易云信IM即时通讯的微信小程序聊天室 5.微信小程序聊天功能 …

codevs 1203 判断浮点数是否相等
1203 判断浮点数是否相等 时间限制: 1 s空间限制: 128000 KB题目等级 : 青铜 Bronze题目描述 Description给出两个浮点数,请你判断这两个浮点数是否相等输入描述 Input Description输入仅一行,包含两个浮点数输出描述 Output Description输出仅一行&…

通过代码自定义cell(cell的高度不一致)
我们知道,在iOS中,自定义cell的方式有两种: 一是通过xib创建 .二是通过代码自定义cell 这里我说下通过代码自定义的cell。 当我们的应用显示的cell比较复杂,显示的行高都不一样,比如新浪微博 这时用系统自带的cell…

通过构建城市来解释HTML,CSS和JavaScript之间的关系
by Kevin Kononenko凯文科诺年科(Kevin Kononenko) 通过构建城市来解释HTML,CSS和JavaScript之间的关系 (The relationship between HTML, CSS and JavaScript explained by building a city) If you have ever visited a walkable city like New York, then you c…

url参数解析 url解析 ?解析成对象
微信小程序开发交流qq群 173683895 承接微信小程序开发。扫码加微信。 正文: 代码: // url参数解析 function getUrlkey(url) {var params {};var urls url.split("?");if (urls[1]) {var arr urls[1].split("&");for …

【bzoj1070】[SCOI2007]修车 最小费用流
原文地址:http://www.cnblogs.com/GXZlegend/p/6798411.html 题目描述 同一时刻有N位车主带着他们的爱车来到了汽车维修中心。维修中心共有M位技术人员,不同的技术人员对不同的车进行维修所用的时间是不同的。现在需要安排这M位技术人员所维修的车及顺序…

“Assign Random Colors” is not working in 3ds Max 2015
Go to Customize -> Preferences…-> General (tab) Uncheck “Default to By Layer for New Nodes”转载于:https://www.cnblogs.com/cindy-hu-23/p/4476293.html

计算机编程课程顺序_您可以在6月开始参加630项免费的在线编程和计算机科学课程...
计算机编程课程顺序Six years ago, universities like MIT and Stanford first opened up free online courses to the public. Today, more than 800 schools around the world have created thousands of free online courses.六年前,麻省理工学院和斯坦福大学等大…

卡片右上角三角形效果,按钮点击变色
微信小程序开发交流qq群 173683895 承接微信小程序开发。扫码加微信。 正文: 效果图: 实现代码: <view classprivilege_list><view classprivilege_card {{in_right_top1?"bg":""}} bindtapin_card id1&g…

数据挖掘基本任务
数据挖掘基本任务 数据挖掘主要做什么?换而言之,数据挖掘主要解决什么问题呢?这些问题,可以归结为数据挖掘的基本任务。 数据挖掘的基本任务包括分类与预测、聚类分析、关联规则、奇异值检测和智能推荐等。通过完成这些任务&#…

41-First Missing Positive
【题目】 Given an unsorted integer array, find the first missing positive integer. For example,Given [1,2,0] return 3,and [3,4,-1,1] return 2. Your algorithm should run in O(n) time and uses constant space. 【analyze】 1.由于是无序的,所以处理起来…

javascript迭代器_JavaScript符号,迭代器,生成器,异步/等待和异步迭代器-全部简单解释...
javascript迭代器by rajaraodv通过rajaraodv JavaScript符号,迭代器,生成器,异步/等待和异步迭代器-全部简单解释 (JavaScript Symbols, Iterators, Generators, Async/Await, and Async Iterators — All Explained Simply) Some JavaScrip…

jquery总结和注意事项
1、关于页面元素的引用通过jquery的$()引用元素包括通过id、class、元素名以及元素的层级关系及dom或者xpath条件等方法,且返回的对象为jquery对象(集合对象),不能直接调用dom定义的方法。 2、jQuery对象与dom对象的转换只有jquer…

第4次作业类测试代码+043+杨晨宇
triangle的代码: package triangle;import java.text.DecimalFormat;public class Triangle {public Triangle() {}/** 判断三角形的类型*/public String triangleshape(int a, int b, int c) {if ((a < 1 || a > 100) || (b < 1 || b > 100) || (c <…

微信小程序让屏幕自动向下滚动
微信小程序开发交流qq群 173683895 承接微信小程序开发。扫码加微信。 正文: wx.pageScrollTo(OBJECT) 基础库 1.4.0 开始支持,低版本需做兼容处理 将页面滚动到目标位置。 OBJECT参数说明: 参数名类型必填说明scrollTopNumber是滚动到…

这就是为什么我们需要在React的类组件中绑定事件处理程序
by Saurabh Misra索拉米斯拉(Saurabh Misra) 这就是为什么我们需要在React的类组件中绑定事件处理程序 (This is why we need to bind event handlers in Class Components in React) While working on React, you must have come across controlled components and event han…

深入JDK源码,这里总有你不知道的知识点!
Java的基础知识有很多,但是我认为最基础的知识应该要属jdk的基础代码,jdk的基础代码里面,有分了很多基础模块,其中又属jdk包下面的lang包最为基础。 我们下面将总结和分析一下lang包下面最为基础和常用的几个部分。 1:常用的对象类…

JS同时上传表单图片和表单信息并把上传信息存入数据库,带php后端源码
微信小程序开发交流qq群 581478349 承接微信小程序开发。扫码加微信。 利用JQ,jquery.form.js,bootstrap实现上传表单图片和表单信息并把上传的图片地址,input填写的信息存入数据库,上传的图片存入服务器。 效果 前端ÿ…

java 的回调函数
在Java中,通常就是编写另外一个类或类库的人(李四)规定一个接口,然后你(张三)来实现这个接口,然后把这个实现类的一个对象作为参数传给别人的程序,别人的程序必要时就会通过那个接口…

无导师学习_如何找到一位导师并加快学习速度:新手指南。
无导师学习by Victor Cassone由Victor Cassone 如何找到一位导师并加快学习速度:新手指南。 (How to find a mentor and accelerate your learning: a beginner’s guide.) One of my biggest regrets while learning to program was that I isolated myself too m…

wamp环境下安装imagick扩展
先上图,如下是安装成功后的phpinfo()界面: 安装步骤: 1、先确定安装版本,比如我的的php : php7.0.12 x86 ts 那么就需要三方版本 要一致:imagick软件本身( 如x86 )、php本身( x86 ts (thread safe) )、php扩展php_ima…

php批量修改文件名
微信小程序开发交流qq群 173683895 承接微信小程序开发。扫码加微信。 正文: 代码 <?php header("Content-type: text/html; charsetutf-8"); //利用PHP目录和文件函数遍历用户给出目录的所有的文件和文件夹,修改文件名称 function f…