-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathsearch.xml
195 lines (195 loc) · 79.3 KB
/
search.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
<?xml version="1.0" encoding="utf-8"?>
<search>
<entry>
<title><![CDATA[【译】Vue 3.0 对 Web 开发意味着什么?]]></title>
<url>%2F2019%2F02%2F26%2Fvue3.0%2F</url>
<content type="text"><![CDATA[原文地址:What Does Vue 3.0 Mean for Web Development? 原文作者 : Matt Maribojoc 译者: Aemple 新年到 Vue2.6悄然发布🎉🎉🎉前言 去年11月,Vue的创建者Evan You向我们展示了Vue 3.0 —— 这是不断上升的Javascript框架的最新版本。这些优化使Vue更高效,更模块化且更易于使用。我将讨论这些变化以及我认为的他们将在Vue 3.0发布后对现有开发产生的影响。 现在的Vue是怎样的? 用他们自己的话来说,Vue是一个“用于构建用户应用程序的渐进式框架”。它的设计非常灵活,既可以将单个Vue库合并到其他项目中,也可以完全用VUE驱动复杂的项目。 Vue通常被视为更易于理解和易于实现的框架之一。支持纯HTML模板,而像React这样的工具是使用Javascript定义DOM元素。 截至2019年初,我们仍然在使用Vue 2.0。虽然与React和Angular相比,Vue仍只占据了很小的市场份额,但Vue的受欢迎程度不断提高。在我看来,Vue 3.0的发布将提升其使用率,并促使其成为其他主要框架的替代品。 下面的图表显示了每个框架在工作中的使用数量。正如你所看到的,VueJS在接近目前的行业标准之前仍然有一条很长的路要走。(资料来源:TechMagic) Vue3.0中最明显的变化在他的演讲中,Evan You强调了Vue 3.0中的五个关键变化: 1、更快 2、更小 3、更易于维护 4、更多的原生支持 5、更易于开发使用 现在让我们深入探讨这些。 让速度更快这个主题占据了Evan You演讲的大部分时间,因为它具有最大的技术变化,显然是Vue目前的主要卖点之一。 VueJS已经以其渲染速度而闻名。在它的比较测试中,它的性能优于其他框架。但是,对Vue2.0代码的边缘情况和修复的数量使得Vue团队决定使用微优化完全重写渲染代码。据Evan You介绍,这些优化可以在安装和初始化速度上增加100%。 与其他框架一样,VueJS使用虚拟DOM来呈现其组件。为了加速渲染过程,必须减少此虚拟DOM的工作负载。Vue3.0中包含了以下特性来满足这个目标: 编译提示——通过检索渲染过程,Vue 3.0将输出更好的编译时提示,这些提示显示了代码如何更好的优化。 组件快速确认——不再通过检查模板对象是否是组件,VUE 3.0将假设大写标记为一个组件。这个假设消除了猜测,加快了渲染过程。 单形调用(Monomorphic Calls)———任何上过计算机科学课程的人-他们的大脑中都有多态性的概念,但是Vue 3.0在呈现过程中使用了单形调用。这种微优化总是将形状相同的对象传递给渲染引擎,这使得Javascript引擎更容易优化。下图来自:Evan You对Vue 3.0的演讲 优化插槽———这个看似复杂的术语实际上归结为一个简单的概念:确保使用它们的实例跟踪依赖关系。目前,每当父组件和子组件具有更新的依赖项时,都将被迫重新呈现。但是,在3.0中,父级和子级将有不同的依赖项,并且只有当它们各自的依赖项发生变化时才会更新。这大大减少了页面上发生的重呈现次数。 静态树提升———虽然这不算Vue3.0的更新(它已经存在于VUE 2.0中),静态树的提升极大地提高了项目速度。提升的意思是不会重新呈现没有任何依赖项的静态元素.这大大减少了虚拟DOM的工作,并节省了许多项目开销。 Proxy Based Observations——Vue 3.0将使用ES2015基于proxy-based observations来跟踪元素的变化。这哥改变不仅消除了Vue 2.0无法支持的几种情况,而且还可以更好地执行。根据You的演讲,这些优化可以使组件实例初始化速度比现在的1vue2.0版本提高100%。 基于Proxy实现比基于Observations的实现快两倍,内存的使用量也仅仅是Vue 2.0中Observations实现的一半。 更轻量级目前,VueJS已经很小了(20 kb Gzip)。然而在Vue3.0中由于tree shaking(消除非重要代码)3.0的估计大小大约是10 kb Gzip。这是通过删除所有对VUE项目非必需的库,并通过import语句(而不是在主src中打包)使用它们。 提高可维护性Flow 到 TypeScript ———为了让更多用户更容易访问,Vue 3.0将从Flow转换为TypeScript。虽然代码库将被重写为使用Typescript,但是然兼容javascript写法。 更加模块化———与目前的Vue相比,VUE 3.0是将更加模块化,它依赖于自己的内部包来运行。这使得它具有可定制性和灵活性,同时也使它具有透明度,从而使开发人员能够真正进入源代码。 编译器重写———这是我最感兴趣的特性之一。这些更改不仅可以有更好的IDE支持,而且现在它创建了源映射,这意味着当出现运行时错误时,它将给出错误的文件位置和行号。如果您现在在使用Vue,您就会知道现在的运行时错误消息对识别问题并没有多大帮助。这个更新应该足以让开发者们心情大好。 更容易定位于Native3.0将是与平台无关的———这意味着它将运行纯Javascript,并且不会在其主构建中使用诸如Node.js之类的Web特性。这使得为Web,iOS或Android构建应用程序变得更加容易。通过定位于Native,Vue使自己更像是React的替代品,它对iOS和Android项目提供了大量支持。 使开发人员的生活更轻松虽然看似简单,但我认为这是使用VueJS的主要原因 - 它简单但功能强大。这些都是突出的方面。 公开Reactivity API———公开后,新的更改将使得开发人员具有显式创建反应性对象的能力。以及创建自定义重新渲染钩子。3.0还解决了VueJS用户的常见抱怨:何时以及为什么我的组件重新渲染? 现在有一个renderTrigged事件,它允许人们看到是什么触发了更新。一个神奇的功能,将使VueJS更加透明。 So What?你可能在想,“那又怎样?人们仍然会使用React 或者 Angular。你也许是对的。 作为当前的行业标准,Reaction和Angular很可能仍然是组件框架中最受欢迎的选择。然而,在Vue 3.0中有一些有趣的东西可以讨论,这可能会使它在未来几年成为一种更具竞争力的选择。 速度 即使是现在,VueJS提供比React或Angular更快的渲染时间。通过Evan You讨论的微优化,Vue可能拥有其他框架的一半渲染时间。这是一个关键点,可以吸引一些开发人员远离其他环境。下表显示了Vue 2.0已经具有的速度和内存优势 - 新的更新应该进一步提高这些优势。 适应性 VueJS旨在易于实施。无论您是要将其添加到现有项目还是使用它来为SPA提供支持,都有大量文档和用例可帮助您定义需求。在Vue 3.0中所做的更改,特别是 reactivity hooks和新的模块化设计,使这个已经灵活的语言更加强大。虽然我将继续强调VueJS的简单性,但有许多功能允许更多技术和经验丰富的开发人员完全控制他们的项目。虽然我将继续强调VueJS的简单性,但是有许多特性允许更多的技术人员和经验丰富的开发人员完全控制他们的项目。 文档 这可能是“我的问题”,但我个人确实认为Vue的文档比React更易于理解。事实上,我甚至从来没有完成过HelloWorld教程或任何关于Vue的内容。文档足以让我理解使用案例并开始使用。你可以自己看看Vue 官方文档。 难度 就像我在谈论文档一样 - Vue非常平易近人。它不仅使用自然HTML,CSS / CSS预处理器(如sass和scss)和Javascript,而且还为相对较新的框架提供了大量的支持和库。对于新开发人员而言,这是非常容易理解的,并且对于高级开发人员来说非常容易扩展。 为了看到Vue 3.0的全部影响,我们将不得不等到2019年某个时候(希望如此)。Evan You在多伦多VueConf展示的功能似乎使Vue更加强大和高效,因此我对新版本寄予厚望。你对Vue 3.0和新的React、Angular有什么看法呢?]]></content>
<categories>
<category>大前端</category>
</categories>
<tags>
<tag>分享</tag>
</tags>
</entry>
<entry>
<title><![CDATA[【译】2019年值得学习的顶尖JavaScript框架和要学习的主题]]></title>
<url>%2F2019%2F02%2F02%2F2019kuangjia%2F</url>
<content type="text"><![CDATA[译者:Aemple 原文作者:Eric Elliott 原文地址: https://medium.com/javascript-scene/top-javascript-frameworks-and-topics-to-learn-in-2019-b4142f38df20 概述白驹过隙,忽然而已。转眼又到了一年的这个时候,旧的一年的结束和新的一年的开始,我们照常对过去的一年做一些总结并对未来的一年做一些展望:我们的目标是寻找出在工作最具有ROI(投资回报率)的学习主题和技术。人们在劳工作中使用了什么?趋势是什么样的?我们并没有试图挑选最好的东西,而是采用数据驱动的方法来帮助你回答面试官分问题(例如:“你知道(填空)吗?)并以此来提高你对技术发展学习的认知。 我们不会去考虑哪些是最快的性能最好的,或者哪些具有最佳的代码质量。我们假设他们都是快速度高性能的,他们都足以支撑完成工作。剩下最重要的重点就是:实际上大规模使用了什么? 组件框架我们首先看到的一个重要的问题是组件框架的当前状态,我们将主要关注三大问题:React,Angular和Vue.js,主要是因为它们的使用度都远远超过了其余框架,是工作中主要采用的技术。 去年我注意到Vue.js增长的速度十分迅猛,并提到它可能会在2018年超越Angular(详细请看:https://medium.com/javascript-scene/top-javascript-libraries-tech-to-learn-in-2018-c38028e028e6 Top JavaScript Libraries & Tech to Learn in 2018)。 但这种情况并没有发生,但它仍在快速增长。我还预测转换React用户会相比Angular困难许多,因为React的用户满意度比Angular强得多 - React用户根本没有令人信服的理由进行切换。这与2018年的预期一致.React在2018年牢牢控制其领先优势。 有趣的是,这三个框架仍然呈指数级增长,同比增长。 预测:React在2019年将继续占主导地位在我留意React的第三年里,React仍然比Angular有更高的满意度(详细可查看:https://2018.stateofjs.com/cn/front-end-frameworks/overview/)。我目前没有看到任何可能在2019年挑战它的东西。除非出现疯狂的大事并且破坏它,否则React将成为2019年底再次击败的框架。 说到React,它在不断变得更好。自React 0.14以来,新的React hooks API取代了class我自己最难容忍的API。(class API仍然有效,但钩子API真的好多了)。React还有许多优秀API改进,比如更好地支持代码拆分和并发渲染(具体请参阅 https://reactjs.org/blog/2018/11/13/react-conf-recap.html), 这都是将使它在2019年难以被击败的理由。现在,React毫无疑问是该领域最具吸引力的前端框架。(译者PS:借用尤大的话 我们应该去关注怎么把一个框架学好,而不是一味的去比较那个更强) 数据展示我们将查看一些关键数据来衡量行业的兴趣和用途: 1、Google搜索趋势。不是我最喜欢的指标,但有利于大局观。 2、包的下载量。这里的目的是在使用框架的过程中捕获真实用户。 3、来自Indeed.com的工作板发布。使用前几年的相同方法来保持一致性。 Google搜索趋势(2014年1月 - 2018年12月) React在2018年1月的搜索趋势中超越了Angular,并在今年年底保持领先地位。Vue.js现在在图表上保持可见位置,但仍然是搜索趋势中的一个小因素。比较去年的图表(2014年1月 - 2017年12月): 包的下载量软件包下载为我们提供了实际使用内容的公平指示,因为开发人员经常在工作时下载所需的软件包。 过于聪明的读者会注意到,有时候他们会从他们内部的公司包装回购中下载这些东西,我回答说:“为什么是,这确实发生了 - 对所有三个框架都有效。”他们都在企业中建立了立足点,并且我对大规模数据的平均功率充满信心。 React月度下载:2014-2018 Angular月度下载:2014-2018 Vue每月下载:2014-2018 让我们看一下下载份额的快速视觉比较: “但你忘记了Angular 1.0的全部内容!它在企业中仍然很大。“ 不,我没忘记。Angular 1.0在企业中仍然使用的方式与Windows XP在企业中仍然使用的方式相同。肯定会有足够多的人注意到这一点,但新版本早已相形见绌,现在它已经不如其他框架重要了。 为什么?因为整个软件行业,以及在所有部门(包括企业)中使用JavaScript的速度都在快速增长,以至于即使旧版应用程序从未升级,新安装也会使旧版安装变得相形见绌。 有关证据,请再看一下这些下载图表。2018年的下载量比前几年的总和还要多。 招聘委员会发布Indeed.com汇总了各种职位委员会的职位发布。每年,我们都会在工作岗位上提及每个框架,以便更好地了解人们的招聘情况。这是今年的样子(2018年12月按框架划分的职位发布): React:24,640 Angular:19,032 jQuery:14,272 Vue:2,816 Ember(未图示):2,397 同样,今年的就业岗位比上一年多得多。我放弃了Ember,因为它显然没有以其他一切的速度增长。我不建议学习它来为将来的工作安排做准备。jQuery和Ember的工作变化不大,但其他一切都增长了很多。 值得庆幸的是,加入软件工程领域的新人数量在2018年也增长了很多,但我们需要继续雇用和培训初级开发人员(这意味着我们需要合格的高级开发人员来指导他们),否则我们将不会保留与爆炸性的就业增长同步。相比之下,这是去年的图表: 平均工资在2018年再次攀升,从每年110,000美元攀升至每年11.1万美元。有趣的是,薪资清单落后于新的雇佣预期,如果招聘经理不调整开发商的市场并提供更大的加薪,他们将难以雇用和留住开发人员。保留和偷猎在2018年仍然是一个巨大的问题,因为员工在其他地方跳槽以获得高薪工作。 保证数据尽量准确的方法:在Indeed.com上进行求职。为了消除误报,我将搜索与关键字“软件”配对以增强相关性的机会,然后乘以~1.5(大致是使用“软件”一词的编程工作列表与不使用“软件”的编程工作列表之间的差异。 )所有SERPS按日期排序,并检查相关性。结果数字不是100%准确,但它们足以满足本文中使用的相对近似值。 下面是译者对框架这块选择的一些评论 有兴趣的可以看看from:Evan You 免责声明:我是Vue的作者。 总的来说,我确实认为React将在2019年继续保持强势,但本文逻辑中存在一些根本性缺陷: 1、我对你的“满意度评分”的定义感到困惑。来自JS状态调查的满意度评级应该计算为使用框架并将再次使用该框架的用户的比例(两者都将使用和不再使用)。在使用过React的14417位用户中,13062会再次使用它,这是90.6%的满意度。对于Vue来说,6374中的5810 = 91.2%。我不确定这是如何转化为React的“用户满意度更高”。 2、我在其他地方已经提到了这一点,但谷歌趋势和NPM下载是非常不准确的指标,有太多变量在起作用。Google Trends关键字的误报是巨大的,无法摆脱; NPM下载与FB / Google的内部使用以及使用NPM /通过CDN /使用CI(具有依赖性缓存与否)的框架的用户百分比有很大关系。与当前使用情况相比,工作计数是延迟曲线。老实说,我已经在框架比较文章中看到过相同的问题方法,所以我只需要在这里指出它。更相关的用户数指标是Chrome devtools扩展的每周活跃用户(React,Vue,Angular)) - React团队还选择在其ReactConf主题演讲中使用它作为用户计数指示器,但由于扩展名不是“官方”,因此Angular数字的准确性要低得多。 3、再一次,我厌倦了看到像这样的文章宣传“学习最主要的框架”,以便人们可以购买作者的指导服务 - 这是一个有兴趣的派对的公然营销。对于读这篇文章的人:不要根据思想领袖的观点选择框架来学习。全部尝试,权衡您的优先级(技术要求,符合您的品味的API,获得工作的重要性等)并做出自己的决定 作者回复: Hi Evan 感谢您的深思熟虑,并祝贺您在Vue.js取得的巨大进步。 1、对不起。我在这些句子中谈论的是React vs Angular,并不打算贬低Vue的出色用户满意度。保持伟大的工作!我澄清了有问题的句子。 2、我没有使用“关键字”搜索趋势,因为你是对的。他们提供了许多误报。但是,当你切换到主题时,那些误报几乎消失了,数据变得足够干净,可以用于像这样的高级概述。RE:npm计数 - 一旦项目变得足够大,使用量就会在整个生态系统中分散,并且这些影响会更均匀地应用于所有顶级框架。如果你的人数不足,那只是因为它的使用尚未充分分散,无法从平均效应中受益 - 这只能加强其他人占有优势的地步。至于“与FB /谷歌的内部使用有很多关系”的其他数字 - 你有没有提到支持这种说法?Re:工作计数,是的,它是一个延迟曲线,Vue.js是块上的新孩子,所以是的,近期,而不是2020年.RE:devtools,这是一个非常冒险的指标,因为许多用户根本不使用它们,而且有些项目比其他项目更好地传授他们的devtools。我们可以整天讨论各种指标的相对优点,但本文的底线是工作规则,其他一切只是“哦,这里有一些其他有趣的数据,所以我们可以证实相对的工作列表数字”。你提出了一些读者应该记住的有趣观点,但为了本文的目的,我坚持使用我的数字。 3、如果Vue.js继续增长并设法赶上,我也会报告。事实上,如果主导框架非常好,(在这种情况下),首先学习它对求职者来说是一个非常好的高投资回报率策略。这只是一个事实,没有任何个人偏见会改变它。如果您对我的培训有所了解,您会发现我的风格是教授超越特定框架的原则,甚至适用于使用完全不同的语言。我对React生态系统没有强烈的既得利益,我坚持这里的建议。 JavaScript基础知识我每年都这么说:关注基本原理。今年你将得到一些额外的帮助。所有软件开发都是组合:将复杂问题分解为更小问题的行为,并为这些较小问题组成解决方案以形成您的应用程序。 但是当我向JavaScript受访者询问软件工程中最基本的问题,“什么是函数组合?”和“什么是对象组合?”时,他们几乎总是无法回答问题,即使他们每天都这样做。 我一直以为这是一个非常严重的问题必须解决,所以我写了一本关于这个主题的书:“Composing Software”(https://leanpub.com/composingsoftware)。 TypeScriptTypeScript在2018年继续增长,并且它继续被高估,因为类型安全似乎不是真实的东西(似乎没有太多减少生产错误密度),并且在没有TypeScript帮助的情况下在JavaScript中进行类型推断确实非常好。您甚至可以使用TypeScript引擎使用Visual Studio Code在普通JavaScript中获取类型推断。或者为您喜欢的编辑器安装Tern.js插件。 对于大多数高阶函数,TypeScript在其表面上继续平坦。也许我只是不知道如何正确使用它(经过多年的定期生活 - 在这种情况下,他们真的需要提高可用性,文档,或两者兼而有之),但我仍然不知道如何正确使用它在TypeScript中输入地图操作,它似乎无视传感器中发生的任何事情。它无法捕获错误,并经常抱怨根本不是错误的错误。 它不够灵活或功能不足以支持我对软件的看法。但我仍然抱有希望,有一天它会添加我们需要的功能,因为在尝试将它用于真实项目时,尽管它的缺点令我感到沮丧,但我也很喜欢能够正确(和有选择地)使用它的潜力当它真的有用时输入东西。 我目前的评价:在非常有限的使用案例中非常酷,但对于大型制作应用程序而言,高估,笨拙且投资回报率非常低。具有讽刺意味的是,因为TypeScript将自己称为“可扩展的JavaScript”。也许他们应该添加一个词:“笨拙地扩展的JavaScript。” 我们对JavaScript的需求是在Haskell之后建模的类型系统,而在Java之后则更少。 其他组要学习的JavaScript技术 GraphQL来查询服务 Redux管理应用程序状态 redux-saga可以隔离副作用 react-feature-toggles可以轻松实现持续交付和测试 RITEway用于精美可读的单元测试 加密行业的崛起去年我预测区块链和fin-tech技术将成为2018年值得关注的重要技术。这一预测很明显。2017-2018的主要主题之一是加密的兴起和建立价值互联网的基础。记住这句话。很快你就会听到很多。 如果你像我一样,自从P2P爆炸以来你一直在关注分散的应用程序,这已经很长时间了。现在,比特币点燃了导火索并展示了分散式应用程序如何使用加密货币自我维持,爆炸是不可阻挡的。 比特币在短短几年内增长了几个数量级。你可能听说2018年是一个“加密的冬天”,并且认为加密行业遇到了一些麻烦。这完全是胡说八道。真正发生的事情是在2017年底,比特币在史诗般的指数增长曲线中再次触及10倍,并且市场有所回落,每当比特币市值增长10倍时就会出现这种情况。 在此图表中,每个箭头从另一个10倍点开始,并指向价格修正的低点。 加密ICO(初始硬币产品)的筹款在2018年初达到顶峰,2017-2018融资泡沫带来了新的就业机会涌入生态系统,在2018年1月达到了超过1万个空缺职位。它已经恢复到大约2,400个(根据Indeed.com),但我们还很早,这个派对刚刚开始。 关于新兴的加密行业还有很多话要说,但那是另一篇博客文章。如果您有兴趣,请阅读“Blockchain Platforms and Tech to Watch in 2019”(https://medium.com/the-challenge/blockchain-platforms-tech-to-watch-in-2019-f2bfefc5c23). 其他技术观察正如去年预测的那样,这些技术在2018年继续爆炸: 人工智能/机器学习正在全面展开2018年结束时的30,000个开放式工作,深度假货,令人难以置信的生成艺术,来自Adobe等公司研究团队的惊人视频编辑功能 - 从未有过更激动人心的时间来探索AI。 渐进式Web应用程序正在迅速成为现代Web应用程序的正确构建方式 - 增加了Google,Apple,Microsoft,Amazon等的功能和支持。令人难以置信的是,我将手机上的PWA视为理所当然。例如,我的手机上没有安装Twitter Android应用程序了。我专门使用Twitter PWA。 AR(增强现实)VR(虚拟现实)MR(混合现实)全部聚集在一起,像Voltron一样成为XR(eXtended Realty)。全职XR沉浸的未来即将来临。我预计在5到10年内大规模采用消费者XR眼镜。内部隐形眼镜2018年开辟了数千个新工作岗位,这个行业将在2019年继续爆发。 有兴趣的可以观看此视频:https://youtu.be/JaiLJSyKQHk 机器人,无人驾驶飞机和自动驾驶汽车自主飞行无人机已经在这里,自动机器人不断改进,更多的自动驾驶汽车在2018年底与我们分享道路。这些技术将继续发展并重塑我们周围的世界到2019年并进入未来20年。 正如预测的那样,量子计算在2018年取得了令人钦佩的进展,而且正如预测的那样,它还没有成为主流。事实上,我的预测,“它可能是2019年或之前的中断真正开始”可能非常乐观。 密码空间的研究人员对量子安全加密算法给予了额外的关注(量子计算将使今天许多关于计算费用昂贵的假设失效,而加密依赖于计算费用昂贵的东西),但尽管不断涌现有趣的研究进展在2018年,最近的报告提出了一些观点: “量子计算在2000年至2017年期间已经在Gartner的炒作名单上进行了11次,每次都在炒作周期的最早阶段列出,并且每次都被称为超过十年。” 这让我想起早期的人工智能工作,这种工作在20世纪50年代开始升温,在1980年代和1990年代取得了有限但有趣的成功,但仅仅在2010年开始变得非常令人兴奋。]]></content>
<categories>
<category>大前端</category>
</categories>
<tags>
<tag>分享</tag>
</tags>
</entry>
<entry>
<title><![CDATA[UnderScore源码看防抖和节流]]></title>
<url>%2F2019%2F01%2F12%2Funderscord%2F</url>
<content type="text"><![CDATA[龟兔赛跑(快不一定好,慢也不一定差) 相信这事一个大家都可以耳熟能详的例子了,兔子跑得很快,这是他胜利的优势,但是同时也是”快”让它有了骄傲的思想,导致自己轻敌儿错失了胜利的机会。 乌龟跑得很慢,但是他很谦虚,一步一个脚印,稳定向前抓住机遇取得了胜利! 浏览器里的”龟兔赛跑” 我们在浏览器中时常会遇到一些高频率事件:onscroll oninput resize onkeyup keydown… 那么当遇到这些的时候我们到底应该让它像”兔子一样快速执行”,还是像”乌龟一样稳步向前”呢? 但是如果快速执行又可能会在较大的项目或者低版本浏览器中造成页面卡顿不流畅影响用户体验(如不理解请谷歌搜索浏览器渲染过程+重绘、回流)!而像乌龟一样稳步向前造成卡顿的几率会小很多,而且对于用户使用的体验基本毫无影响!所以我们还是稳步向前为好! 那么怎么做到稳步执行呢?优化高频事件 》》降低代码执行频率 那么怎么做到降低代码执行频率呢?降低代码执行频率 》》 throttle(节流)|| debounce(防抖) throttle(节流)和 debounce(防抖) 请先记住两个概念:节流>间隔固定时间执行,防抖>你不停止我就不执行。请您记住,记住,记住!!! 不要再分不清这两个词语哪个是哪个了!!!! throttle(节流) 直接上代码,咱们先看一个简单版本容易理解的。 1234567891011121314151617181920212223 function throttle(fn, threshhold=150) { var timeout;//方便清除定时器 var start = new Date;//开始的时间 return function () { var context = this, args = arguments, curr = new Date() - 0 clearTimeout(timeout)//总是干掉事件回调(与后面的“让方法在脱离事件后也能执行一次”对应) if(curr - start >= threshhold){ fn.apply(context, args) start = curr //其实到这里我们就已经实现了节流的逻辑 }else{ //让方法在脱离事件后也能执行一次(比如我们最后一次点击一个按钮,点击后按照上面的逻辑当小于threshhold是不会执行这次点击事件的回调函数的,所以加上这个定时器确保最后一次无论间隔时间多大都可以执行) timeout = setTimeout(function(){ fn.apply(context, args) }, threshhold); } }}var logger = throttle(function(e) { console.log(e.pageX, e.pageY)});// 绑定监听document.querySelector("#btn").addEventListener('click',logger); 下面看看UnderScore对throttle(节流)的封装123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566function throttle(func, wait, options) {; let args, context, previous = 0, timeout; let later = function () {//最后一次定时器中的回调 func.apply(context, args); args = context = null } let throttled = function () { args = arguments; context = this; let now = Date.now(); // 现在的时间 let remaning = wait - (now - previous); if (remaning <= 0) { if (timeout) {//多次连续点击的时候就清除定时器,因为它不是最后一次点击,只有最后一次点击后才会保留定时器 clearTimeout(timeout); timeout = null; } func.apply(context, args); previous = now; } else if (!timeout && options.trailing !== false) {//如果我们不传trailing那么就是undefined同样不等于flase //先判断是否存在timeout,存在就不增加定时器,避免多次定义定时器 timeout = setTimeout(later, remaning); } } return throttled; } function logger() { console.log('logger'); } //参数trailiing:达到让最后一次事件触发后回调方法还是能执行的效果 btn.addEventListener('click', throttle(logger, 1000, { trailiing: true })); //参数leading:达到让第一次事件触发后不立刻执行回调 function throttle(func, wait, options) { let args, context, previous = 0, timeout; let later = function () { previous = options.leading === false ? 0 : Date.now(); //第二步:定时器回调中让previous回归正常 func.apply(context, args); args = context = null } let throttled = function () { args = arguments; context = this; let now = Date.now(); if (!previous && options.leading === false) previous = now; //第一步:使remaning一定大于0以此来达到让它走 else if,也就是定义定时器延迟处理事件。 let remaning = wait - (now - previous); if (remaning <= 0) { if (timeout) { clearTimeout(timeout); timeout = null; } func.apply(context, args); previous = now; } else if (!timeout && options.trailing !== false) { timeout = setTimeout(later, remaning); } } return throttled; } function logger() { console.log('logger'); } // btn.addEventListener('click', throttle(logger, 1000, { trailiing: true })); // 延迟第一次点击 是不生效的 btn.addEventListener('click', throttle(logger, 1000, { leading: false })); 此处是自己对UnderScore中throttle源码的简单重写。如有不懂的请私信我。。 debounce(防抖) 防抖实现十分简单1234567891011121314function debounce(func,wait) { let timeout; return function () { clearTimeout(timeout); //有定时器就先清掉,始终保证只有一个定时器 timeout = setTimeout(() => { func.apply(this,arguments); timeout = null; }, wait); } } function logger(e) { console.log('logger'); } btn.addEventListener('click', debounce(logger,1000)); 但是呢,这样又有点bug,那就是我们点击第一次也要等很久的定时器时间间隔才可以看到效果,而我们有时会希望的是点击了马上就有效果。 下面看看UnderScore对 debounce(防抖)的封装12345678910111213141516171819function debounce(func,wait,immediate) { let timeout; return function () { clearTimeout(timeout); if(immediate){ let callNow = !timeout; //第一次点击的话timeout就是undefined取反就是true,就会执行下一行,第二次点击的话就timeout不为空就不会按照原来的逻辑执行了。这样也就达到了点击第一次立即执行的效果。 if(callNow) func.apply(this, arguments); } timeout = setTimeout(() => { func.apply(this,arguments); timeout = null; }, wait); } } function logger(e) { console.log('logger',e); } // 第三个参数 表示首次 先触发一下 btn.addEventListener('click', debounce(logger,1000,true)); 上面就是UnderScore对节流、防抖的基本实现了,当然还有一个取消的方法,但是那个很简单可以自行去看一看 链接:https://github.com/jashkenas/underscore/blob/master/underscore.js 文章未完待续…ToDo:(1)将文章思路再理一遍,配些动图和例子一步步的实现一下防抖节流 ToDo:(2)将lodash的防抖节流一步步实现一遍 PS:过年在家长膘,写得有点笼统 还望大佬们海涵]]></content>
<categories>
<category>大前端</category>
</categories>
<tags>
<tag>分享</tag>
</tags>
</entry>
<entry>
<title><![CDATA[JS漫威--requestAnimationFrame]]></title>
<url>%2F2018%2F11%2F19%2FrequestAnimationFrame%2F</url>
<content type="text"><![CDATA[日常前戏不知道你有没有遇到过以下问题 不知道setTimeout该设置多大时间好?算了,蒙一个吧! 如何渲染几万条数据并不卡住界面?嗯…..懒加载 做动画有需要循环间隔必须足够短,这样才能让不同的动画效果显得平滑流畅;另一方面,循环间隔还要足够长,这样才能确保浏览器有能力渲染产生的变化。 . . . . . . . 想知道更好的答案,来到我房间咱们相互深入了解一下(贱贱的小眼神) requestAnimationFrame是个啥玩意?1requestAnimationFrame是浏览器用于定时循环操作的一个接口,类似于setTimeout,主要用途是按帧对网页进行重绘 为什么需要requestAnimationFrame这玩意,setTimeout做动画不好吗?css动画不好吗?1234567css实现的动画的优势就是浏览器知道动画的开始及每一帧的循环间隔,能够在恰当的时间刷新UI,给用户一种流畅的体验但是`css`动画并不能很精确的人为控制。而`setInterval`或`setTimeout`实现的JavaScript动画虽然可以精确的控制,但是却并不可靠了他不能自己精确计算出指向动画的时间,因为浏览器压根就无法保证每一帧渲染的时间间隔,一般情况下,每秒平均刷新次数能够达到60帧,就能够给人流畅的体验,即每过 1000/60 毫秒渲染新一帧即可。但是这事一般情况! 因此requestAnimationFrame应运而生,他能自己随着浏览器的刷新机制指定自己执行动画的恰当时间(一般浏览器的显示帧率是60fps,差不多每帧间隔16.7ms)来看看阮大大的解释: 设置这个API的目的是为了让各种网页动画效果(DOM动画、Canvas动画、SVG动画、WebGL动画)能够有一个统一的刷新机制,从而节省系统资源,提高系统性能,改善视觉效果。代码中使用这个API,就是告诉浏览器希望执行一个动画,让浏览器在下一个动画帧安排一次网页重绘。requestAnimationFrame的优势,在于充分利用显示器的刷新机制,比较节省系统资源。显示器有固定的刷新频率(60Hz或75Hz),也就是说,每秒最多只能重绘60次或75次,requestAnimationFrame的基本思想就是与这个刷新频率保持同步,利用这个刷新频率进行页面重绘。此外,使用这个API,一旦页面不处于浏览器的当前标签,就会自动停止刷新。这就节省了CPU、GPU和电力不过有一点需要注意,requestAnimationFrame是在主线程上完成。这意味着,如果主线程非常繁忙,requestAnimationFrame的动画效果会大打折扣。 说了这么多,下面来看看它怎么用API1234567window.requestAnimationFrame(callback);callback一个指定函数的参数,该函数在下次重新绘制动画时调用。这个回调函数只有一个传参,DOMHighResTimeStamp,指示requestAnimationFrame() 开始触发回调函数的当前时间(performance.now() 返回的时间)。返回值一个 long 整数,请求 ID ,是回调列表中唯一的标识。是个非零值,没别的意义。你可以传这个值给 window.cancelAnimationFrame() 以取消回调函数。 下面看一个使用例子: 123456789function animationWidth() { var div = document.getElementById('box'); div.style.width = parseInt(div.style.width) + 1 + 'px'; if(parseInt(div.style.width) < 200) { requestAnimationFrame(animationWidth) }}requestAnimationFrame(animationWidth); 这个例子可以平滑的增大宽度(个人感觉有点像递归的感觉) 还想看其他例子请到 例子一:来源大漠例子二:来源思否他们都对setTimeout和requestAnimationFrame做了对比实验。很直观!!! 最后来回答文章开始的问题 不知道setTimeout该设置多大时间好?requestAnimationFrame自动调节玮最佳 如何渲染几万条数据并不卡住界面?通过 requestAnimationFrame 来每 16 ms 刷新一次,请看下面代码 12345678910111213141516171819202122232425262728setTimeout(() => { // 插入十万条数据 const total = 100000 // 一次插入 20 条,如果觉得性能不好就减少 const once = 20 // 渲染数据总共需要几次 const loopCount = total / once let countOfRender = 0 let ul = document.querySelector("ul"); function add() { // 优化性能,插入不会造成回流 const fragment = document.createDocumentFragment(); for (let i = 0; i < once; i++) { const li = document.createElement("li"); li.innerText = Math.floor(Math.random() * total); fragment.appendChild(li); } ul.appendChild(fragment); countOfRender += 1; loop(); } function loop() { if (countOfRender < loopCount) { window.requestAnimationFrame(add); } } loop(); }, 0); 做动画有需要循环间隔必须足够短,这样才能让不同的动画效果显得平滑流畅;另一方面,循环间隔还要足够长,这样才能确保浏览器有能力渲染产生的变化。 . . . . . . .]]></content>
<categories>
<category>JavaScript</category>
</categories>
<tags>
<tag>分享</tag>
</tags>
</entry>
<entry>
<title><![CDATA[从零开始使用 Webpack 4 和 Babel 7 搭建 React 开发环境(1)]]></title>
<url>%2F2018%2F11%2F16%2Fwebpack-react%2F</url>
<content type="text"><![CDATA[这一次搭建的是最简单的运行环境 后续将会升入第一步 创建一个文件夹 npm init npm install webpack webpack-cli –save-dev //这些都是webpack核心包 编译器打开文件夹第二步 打开package.json 修改script为 “dev”:”webpack –mode development” //用npm run start就是运行webpack的意思 ps如果出现找不到命令的情况请先 npm install -g webpack!第三步 npm install @babel/core babel-loader @babel/preset-env @babel/preset-react –save-dev @babel/core babel-loader 核心包 @babel/preset-env es6+变为es5 @babel/preset-react 解析react语法 为啥加@ 为了把他们都安装在babel文件夹下第四步创建一个.bablerc文件(指定你要用哪些babel解析规则)123{ "presets": ["@babel/preset-env", "@babel/preset-react"]} 创建一个webpack.config.js123456789101112131415161718192021const HtmlWebpackPlugin = require('html-webpack-plugin');//使用插件module.exports = { module: { rules: [ { test: /\.js/,匹配.js后缀的文件 exclude: /node_modules/,排除这个文件夹不打包 use: { loader: "babel-loader" } } ] }, plugins: [ new HtmlWebpackPlugin({ template: "src/index.html",匹配的模板 filename: "index.html"输出文件名 }) ]} 第五步现在就是写react啦 记得安装react react-dom src/index.js 12345import React from 'react';import ReactDom from 'react-dom';import FormContainer from './components/FormContainer';ReactDom.render(<FormContainer />, document.getElementById("root")); src/index.html 12345678910<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>hello</title></head><body> <div id="root"></div></body></html> src/components/FormContainer.js 12345678910111213141516171819202122import React, { Component } from 'react';import Input from './Input';class FormContainer extends Component { constructor() { super(); this.state = { title: 'hello' }; } render() { return ( <form id="article-form"> <Input title={ this.state.title } /> </form> ) }}export default FormContainer; src/components/Input.js1234567891011121314151617import React from 'react';import PropTypes from 'prop-types';const Input = ({ title }) => { return ( <div> <div>{ title } world</div> <input type="text" /> </div> )}Input.propTypes = { title: PropTypes.string.isRequired}export default Input; 现在再来npm run dev 就ok啦 打包出了一个文件但是现在每次都要手动重新打包 很累 安装插件 webpack-dev-server 为package.js文件夹中script增加一行 “start”:”webpack-dev-server –open –mode development” 这样编译完了就能自动打开浏览器窗口 还可以修改后自动打包编译好啦 这样就完成了一个最简单的react开发环境配置]]></content>
<categories>
<category>React</category>
</categories>
<tags>
<tag>分享</tag>
<tag>导航</tag>
</tags>
</entry>
<entry>
<title><![CDATA[ES6之---读懂let才能少踩坑]]></title>
<url>%2F2018%2F06%2F21%2FES6-let%2F</url>
<content type="text"><![CDATA[开聊吧!(前面一小部分大佬们可以自动忽略) 首先,打脸我的无知! 在刚接触ES6的时候,我就「以为」我理解了let。然后漫长的自学道路上,let一次又一次的让我认识到了自己的无知。 希望写了这篇文章之后能用我的无知,让在这条道路上的人能少踩些坑。 初识let 和很多人一样,在听说了ES6很好用之后,就马不停蹄的去学习这门充满着语法糖的东西。开始抱着emmmm快速把es6过一遍的念头去了菜鸟教程(因为觉得这里的教程很简洁,但是希望大家以后慎重选择初学教程!!!) 如图所示,这就是我对他的初始理解—一个解决javascript没有块级作用域的东西。嗯….就是这样也仅此而已。 let浅解《1》let 声明的变量的作用域是块级的;1234567{ let a = 10; var b = 1;}a // ReferenceError: a is not defined.b // 1 用法类似于var,但是所声明的变量,只在let命令所在的代码块内有效. 说说这个「块级作用域」里面的坑吧!!!首先,用阮大神的一个示例来说说过第一个坑 1234567var a = [];for (var i = 0; i < 10; i++) { a[i] = function () { console.log(i); };}a[6](); 输出几呢?是6吗? 答案是10 为什么呢?因为上面代码中,变量i是var命令声明的,在全局范围内都有效,所以全局只有一个变量i。每一次循环,变量i的值都会发生改变,而循环内被赋给数组a的函数内部的console.log(i),里面的i指向的就是全局的i。也就是说,所有数组a的成员里面的i,指向的都是同一个i,导致运行时输出的是最后一轮的i的值,也就是 10。 那么怎么解决呢?ES6之前的解决方式–构造闭包形成不销毁的作用域保存变量 1234567var a = [];for (var i = 0; i < 10; i++) { (function (arg) {a[i] = function () { console.log(arg); }})(i);}a[6](); //6 ES6的解决方式 1234567var a = [];for (let i = 0; i < 10; i++) { a[i] = function () { console.log(i); };}a[6](); // 6 代码中,变量i是let声明的,当前的i只在本轮循环有效,所以每一次循环的i其实都是一个新的变量,所以最后输出的是6。用ES5的代码描述就是这样的! 1234567891011121314"use strict";var a = [];var _loop = function _loop(i) { a[i] = function () { console.log(i); };};for (var i = 0; i < 10; i++) { _loop(i);}a[6](); // 6 再来一个平常码代码经常会遇到的,面试也会经常遇到。123456var liList = document.querySelectorAll('li') // 共5个lifor( var i=0; i<liList.length; i++){ liList[i].onclick = function(){ console.log(i) }} 打印多少呢?0,1,2,3,4 还是 5,5,5,5,5?相信大家大家应该都知道依次点击 li 会打印出 5 个 5。 如果把 var i 改成 let i,就会分别打印出 0、1、2、3、4: 123456var liList = document.querySelectorAll('li') // 共5个lifor( let i=0; i<liList.length; i++){ liList[i].onclick = function(){ console.log(i) }} 阐述一下我的理解吧! for( let i = 0; i< 5; i++) 这句话的圆括号之间,有一个隐藏的作用域。 for( let i = 0; i< 5; i++) { 循环体 } 在每次执行循环体之前,JS 引擎会把 i 在循环体的上下文中重新声明及初始化一次。 用ES5的代码描述就是这样的! 12345678910111213'use strict';var liList = document.querySelectorAll('li'); // 共5个livar _loop = function _loop(i) { liList[i].onclick = function () { console.log(i); };};for (var i = 0; i < liList.length; i++) { _loop(i);} 总结:希望大家在已有遇到跟循环 异步事件之类的问题的时候多注意下,不要掉坑里了☺ 《2》let 声明的变量不存在变量提升,有暂时性死区;先来解释解释这两个吧 变量提升 12345console.log(foo); // 输出undefinedconsole.log(bar); // 报错ReferenceErrorvar foo = 2;let bar = 2; let不像var那样会发生“变量提升”现象。所以,变量一定要在声明后使用,否则报错。 暂时性死区 12345let x = 'global'{ console.log(x) // Uncaught ReferenceError: x is not defined let x = 1} 存在全局变量x,但是块级作用域内let又声明了一个局部变量x,导致后者绑定这个块级作用域,所以在let声明变量前,对tmp赋值会报错。 在详细的解释这个问题之前,我们先来弄懂ES6之前,我们的作用域里的变量预解释。 12345678var a = 1;function b(params) { var c = 2; console.log(params);}console.log(a);b(3); 红色框框中的部分是在b函数被调用的时候才会按照预解释规则一步步产生,现在写出来是为了方便你们理解。正因为b函数被预先声明且赋值了,所以在b函数之前调用他就能得到结果,代码如下,相信你又学到不少吧! 12345b(3);function b(params) { var c = 2; console.log(params);} 然后就是函数执行的第二步了 够清楚!!!!够明了吧!!! 这个我们弄清楚了 就再把let的说一遍 那么上面的问题你自然就豁然开朗了。 关于let的是这样的 找到所有用 let 声明的变量,在环境中「创建」这些变量 开始执行代码(注意现在还没有初始化也没有假装赋值为undefined) 执行 let声明的变量时,将 该变量 「初始化直接赋值」 现在关于上面的不存在变量提升,有暂时性死区你应该都懂了吧。关于暂时性死区是因为let声明的变量有块级作用域而且没有变量提升所以就产生了 也来看看暂时性死区在es6之前的环境里是怎样的吧。 123456789101112131415//es6中let x = 'global'{ console.log(x) // Uncaught ReferenceError: x is not defined let x = 1}//之前版本的环境中'use strict';var x = 'global';{ console.log(_x); // Uncaught ReferenceError: x is not defined var _x = 1;} 《3》let 不能重复声明已存在的变量这个知识点就基本没啥坑了 自己注意点儿就好 1234567891011// 报错function () { let a = 10; var a = 1;}// 报错function () { let a = 10; let a = 1;} 总结 总共也就三个知识点:完全掌握还是要多用!!! 1、let的块级作用域! 2、let声明的变量不存在变量提升,有暂时性死区! 3、let声明的变量不允许重复声明,无论重复用var或者其他声明都不行! let的故事就这样暂时说完啦(疯狂求有位大佬来带带我啊) 不知不觉又晚上10点多了 该回寝室了 哈哈 如果学到了就给我个小心心吧 哈哈哈]]></content>
<categories>
<category>大前端</category>
</categories>
<tags>
<tag>分享</tag>
</tags>
</entry>
<entry>
<title><![CDATA[浅谈Http1.0/Http1.1/Http2.0/Https]]></title>
<url>%2F2018%2F06%2F08%2Fhttp%2F</url>
<content type="text"><![CDATA[首先来看看Http的发展(此图来自 code小生)HTTP1.0最早在网页中使用是在1996年,那个时候只是使用一些较为简单的网页上和网络请求上,而HTTP1.1则在1999年才开始广泛应用于现在的各大浏览器网络请求中,同时HTTP1.1也是当前使用最为广泛的HTTP协议,最后一个就是2015年发布的http2.0。 HTTP 1.0 → HTTP 1.1长连接HTTP 1.1默认支持长连接,减少了TCP连接次数,节约开销。 HTTP 1.0所保持的TCP每次只能处理一个请求,最典型的就是pipline管线化模型,虽然能一次性接收多个请求,但是还是得按顺序一次处理一个请求,这样很容易造成后续请求等待前序请求完成,造成阻塞,也就是我们常说的”线头阻塞”。 总结:HTTP 1.0需要使用keep-alive参数来告知服务器建立长连接,而HTTP 1.1默认支持长连接,减少了TCP连接次数,减少了开销和延迟!!! _缓存_HTTP1.0中主要使用header里的If-Modified-Since,Expires来做为缓存判断的标准。 HTTP1.1则引入了更多的缓存控制策略例如Entity tag,If-Unmodified-Since, If-Match, If-None-Match等更多可供选择的缓存头来控制缓存策略 新增状态码:HTTP1.1 中新增了24个错误状态响应码,如409(Conflict)表示请求的资源与资源的当前状态发生冲突;410(Gone)表示服务器上的某个资源被永久性的删! http1.1带宽优化HTTP 1.1支持只发送header信息(不带任何body信息),如果服务器认为客户端有权限请求服务器,则返回100,否则返回401。客户端如果接受到100,才开始把请求body发送到服务器。这样当服务器返回401的时候,客户端就可以不用发送请求body了,节约了带宽。另外HTTP还支持传送内容的一部分。这样当客户端已经有一部分的资源后,只需要跟服务器请求另外的部分资源即可。这是支持文件断点续传的基础。HTTP1.1在请求头引入了range头域,它允许只请求资源的某个部分,即返回码是206(Partial Content),这样就方便了开发者自由的选择以便于充分利用带宽和连接。 HOST域HTTP 1.1支持host域,服务端可以通过host域设置多个虚拟站点来共享一个ip和端口。因为随着虚拟主机技术的发展,在一台物理服务器上可以存在多个虚拟主机,并且它们共享一个IP地址。HTTP1.1的请求消息和响应消息都应支持Host头域,且请求消息中如果没有Host头域会报告一个错误(400 Bad Request)。HTTP1.0中认为每台服务器都绑定一个唯一的IP地址,因此,请求消息中的URL并没有传递主机名(hostname) HTTP 1.1 → HTTP 2.0多路复用HTTP 2.0使用多路复用技术,使用一个TCP连接_并发_处理多个请求,不但节约了开销而且可处理请求的数量也比HTTP 1.1大了很多。 当然HTTP1.1也可以多建立几个TCP连接,来支持处理更多并发的请求,但是创建TCP连接本身也是有开销的。TCP连接有一个预热和保护的过程,先检查数据是否传送成功,一旦成功过,则慢慢加大传输速度。因此对应瞬时并发的连接,服务器的响应就会变慢。所以最好能使用一个建立好的连接,并且这个连接可以支持瞬时并发的请求。 头部压缩HTTP 1.1不支持header数据压缩,HTTP 2.0使用HPACK算法对header的数据进行压缩,使得数据传输更快。 服务器推送当我们对支持HTTP 2.0的服务器请求数据额时候,服务器会顺便把一些客户端需要的资源一起推送到服务器,这种方式适用于加载静态资源,节约带宽。服务器端推送的这些资源其实存在客户端的某处地方,客户端直接从本地加载这些资源就可以了,不用走网络,速度自然是快很多的。 注意 HTTP → HTTPS HTTPS = HTTP + TLS/SSL加密 + 认证 + 完整性保护 (80 443)在讲 HTTPS 之前,我们先来看看 HTTP 有哪些不足: 使用明文通信,内容可能会被窃听 不验证通信双方身份,有可能遭遇伪装 无法证明报文的完整性,内容可能遭到篡改 为了解决这些不足,所以HTTPS 应运而生,先看看https的特性: TLS/SSL内容加密 数字证书(CA)验明身份: 防范中间人攻击 MD5、SHA-1等散列值方法防止信息篡改(中间人攻击:运营商等) 先来谈谈“对称加密”和“非对称加密”的概念对称加密 所谓的“对称加密技术”,意思就是说:“加密”和“解密”使用相同的密钥。这个比较好理解,就好比你用 7zip 或 WinRAR 创建一个带密码(口令)的加密压缩包,当你下次要把这个压缩文件解开的时候,你需要输入同样的密码,在这个例子中,密码/口令就如同刚才说的“密钥”。 对称加密是最快速、最简单的一种加密方式,加密(encryption)与解密(decryption)用的是同样的密钥(secret key),这种方法在密码学中叫做对称加密算法,对称加密有很多种算法,由于它效率很高,所以被广泛使用在很多加密协议的核心当中。 非对称加密 所谓的“非对称加密技术”,意思就是说:“加密”和“解密”使用不同的密钥,这玩意儿比较难理解,也比较难想到,当年“非对称加密”的发明,还被誉为“密码学”历史上的一次革命。非对称加密为数据的加密与解密提供了一个非常安全的方法,它使用了一对密钥,公钥(public key)和私钥(private key),私钥只能由一方安全保管,不能外泄,而公钥则可以发给任何请求它的人,非对称加密使用这对密钥中的一个进行加密,而解密则需要另一个密钥。 总结:非对称相对更安全,但是性能要求更高!https加密方式虽然TLS/SSL采用公开密钥这种非对称加密方式,但是HTTPS并不是全部使用非对称加密,而是使用混合加密方式,即:公开密钥(非对称加密)+共享密钥(对称加密) 因为公开密钥与共享密钥加密相比,其处理速度要慢很多。所以HTTPS冲锋利用了两者各自的优势,将多种方法组合起来用于通信。https在交换密钥环节使用公开密钥加密方式,之后建立的通信交换报文阶段则使用共享密钥加密方式 证明公开密钥的正确性的证书遗憾的是, 公开密钥加密方式还是存在一些问题的, 那就是无法证明公开密钥本身就是货真价实的公开密钥. 比如, 正准备和某台服务器建立公开密钥加密方式下的通信时, 如何证明收到的公开密钥就是原本预想的那台服务器发行的公开密钥. 或许在公开密钥传输途中, 真正的公开密钥已经被攻击者替换了. 为了解决上述问题, 可以使用有数字证书认证机构(CA)和其他相关机关颁发的公开密钥证书 基本流程为: 1.服务器把自己的公开密钥登录至数字证书认证机构 2.数字证书认证机构用自己的私有密钥向服务器的公开密钥署数字签名并颁发公钥证书 3.客户端拿到服务器的公钥证书后, 使用数字证书认证机构的公开密钥, 向数字证书认证机构验证公钥证书上的数字签名, 以确认服务器的公开密钥的真实性 4.使用服务器的公开密钥对报文加密后发送 5.服务器用私有密钥对报文解密 性能问题通常我们会认为,使用HTTPS会导致网站加载速度变慢。实际上,只要我们合理优化使用HTTPS过程,使用HTTPS可能会比使用HTTP还快!使用HTTPS相比于HTTP所增加的延迟点: HTTP 302 跳转到 HTTPS 的耗时 CPU 进行 RSA 加解密运算的耗时 请求和验证 CA 所花的时间 优化方式: 使用 HSTS 技术,去掉从80跳转到443的跳转(HSTS使用的是内部307跳转技术,不会产生多余的网络请求) PS:302 和 307 效果相同,只是307强制使用post 使用专门的加解密硬件处理加解密,减轻CPU负担。这样不仅减少了处理时间,所能承受的qps也会增加。 减少证书链,减少 CA 请求时间 session复用,减少建立连接的次数 为什么不都使用https 性能问题 金钱问题 参考HTTP1.0、HTTP1.1 和 HTTP2.0 的区别HTTP、SSL/TLS和HTTPS协议的区别与联系]]></content>
<categories>
<category>计算机基础</category>
</categories>
<tags>
<tag>分享</tag>
</tags>
</entry>
<entry>
<title><![CDATA[JS学习笔记--常用数组去重、伪数组转数组]]></title>
<url>%2F2018%2F05%2F06%2Fjs-arr%2F</url>
<content type="text"><![CDATA[话不多说,直接开干吧!数组去重第一种、最简单的思路–循环1234567891011121314//上面的ary总共14项,每一项都和后面的所有项比,最后一项的后面没有内容了,所以我们不需要再比较,所以总共循环length-1次for (var i = 0; i < ary.length - 1; i++) { var cur = ary[i];//=>当前项 //这一项和后面的每一项进行比较 //i+1:把当前项和它后面项比较,当前项索引是i,后一项索引是i+1 for (var j = i + 1; j < ary.length; j++) { if (cur === ary[j]) { //如果比较的这一项和当前项相同,在原有数组中把作比较的这一项删除掉(作比较这一项的索引是j) ary.splice(j, 1); //这里会造成一个问题使用splice删除数组中的某一项后,删除这一项后面的每一项索引都要向前进一位(在原有索引上减一),但是下一次循环还是会j++造成被删的后一项直接被循环掠过,所以此时应该j--来解决这个问题。 j--; } }} 当然我们也可以这样来玩玩儿 123456789101112for (var i = 0; i < ary.length - 1; i++) { var cur = ary[i]; //二次循环只有不执行去重的时候我们再j++ for (var j = i + 1; j < ary.length;) { if (cur === ary[j]) { ary.splice(j, 1); } else { j++; } }} 还可以在偷懒一点 1234567for (var i = 0; i < ary.length - 1; i++) { var cur = ary[i]; for (var j = i + 1; j < ary.length;) { //三目运算代替if else 程序员必备良品啊 cur === ary[j] ? ary.splice(j, 1) : j++; }} 第二种方法、利用对象去重123456789101112var obj = {};for (var i = 0; i < ary.length; i++) { var cur = ary[i]; if (typeof obj[cur] !== 'undefined') { //对象中已经存在该属性说明当前项是数组中的重复项,用最后一项来代替这一项,然后删除最后一项(这里也可以用splice,但是用splice更耗费性能) ary[i] = ary[ary.length - 1]; ary.length--; i--; continue; } obj[cur] = cur;} 第三种、indexOf法去重1234567891011for (var i = 0; i < ary.length; i++) { var cur = ary[i]; //把当前项后面的那些值以一个新数组返回。 var curNextAry = ary.slice(i + 1); //遍历后面的项组成的新数组。 if (curNextAry.indexOf(cur) > -1) { //后面项组成的数组中包含当前这一项就把当前这一项删除 ary.splice(i, 1); i--; }} 第四种、排序后相邻去重法12345678910111213function uniq(ary){ //先把数组排序,相同的元素就会相邻。 ary.sort(); var temp=[ary[0]]; for(var i = 1; i < ary.length; i++){ //遍历数组 与新数组最后一个值比较(也就是和原来他相邻的那个数比较) if( ary[i] !== temp[temp.length-1]){ //不相同就加入新数组 temp.push(ary[i]); } } return temp;} 第五种、ES6新增方法Set1console.log(new Set(arr));//这样就能得到一个新的去重类数组 怎么把类数组转换为数组就看下面的方法吧 当然,还有其他的方法这里只是列举了部分。 类数组转数组第一种、最笨的方法—声明一个空数组,通过遍历伪数组把它们重新添加到新的数组中。12345var aLi = document.querySelectorAll('li'); var arr = []; for (var i = 0; i < aLi.length; i++) { arr[arr.length] = aLi[i] } 第二种、使用call或者apply改变this指向,让类数组拥有数组的方法1var arr = Array.prototype.slice.call(aLi); 讲讲他的原理吧 首先,模拟下slice的内部实现机制 1234567891011Array.prototype.slice = function(start,end) { var result = new Array(); //没传参数给的默认值 var start = start || 0; var end = end || arr.length; for (var i = start; i < end; i++) { // this=》当前调用slice的那个数组 result.push(this[i]); } return result;} 由上面的代码可以发现改变slice的this指向后可以构建出一个新数组。 第三种、ES6中数组的新方法 from()1var newArg = Array.from(aLi); 当然jQuery也提供了两种方法makeArray(),toArray()。当然,还有其他的方法这里只是列举了部分。 😁这篇笔记到这里就结束啦😁]]></content>
<categories>
<category>大前端</category>
</categories>
<tags>
<tag>分享</tag>
</tags>
</entry>
<entry>
<title><![CDATA[《高新能javascript》学习笔记]]></title>
<url>%2F2018%2F05%2F03%2Fnote-gxn%2F</url>
<content type="text"><![CDATA[这是在学习《高新能javascript》的时候做的总结 不够清晰 有需要的可以联系我 发xmind文件]]></content>
<categories>
<category>计算机基础</category>
</categories>
<tags>
<tag>分享</tag>
</tags>
</entry>
<entry>
<title><![CDATA[Vue CLI使用scss]]></title>
<url>%2F2018%2F04%2F12%2Fvue%2F</url>
<content type="text"><![CDATA[在Vue CLI脚手架中使用scss今天学习vue当中遇到了如何配置scss的问题经过查证,写出记录。 第一步: npm install sass-loader node-sass 或者 yarn add sass-loader node-sass 如果node-sass在Windows中安装失败(需要Python和C++构建工具),大家可以使用cnpm单独安装node-sass 第二步: 在vue文件中使用 12345678910111213141516171819<style lang='scss'>![scss](https://tse4-mm.cn.bing.net/th?id=OIP.HuHbi6D0rpzsTenMxWgfXgHaFj&w=253&h=184&c=7&o=5&pid=1.7)#app { @import url('./assets/aaa.scss'); // 引入单独的scss文件 font-family: 'Avenir', Helvetica, Arial, sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; text-align: center; color: #2c3e50; margin-top: 60px;} 这样就很愉快的完成了!使用Sass同理## Sass使用]]></content>
<categories>
<category>Vue</category>
</categories>
<tags>
<tag>分享</tag>
<tag>导航</tag>
</tags>
</entry>
<entry>
<title><![CDATA[天上便落下一粒沙,从此便有了撒哈拉--初入大学]]></title>
<url>%2F2018%2F04%2F09%2FSH-1%2F</url>
<content type="text"><![CDATA[我的大学生活 “准”大学生活: 高考后感觉身上的担子轻了,是到放松任性玩儿的时候了,于是高考后的六月七月都被我放肆的挥霍了。就在七月末的时候,突然冒出了一个奇怪的想法。 我想去找一份工作尝试着靠自己的能力来拿到一笔完完全全属于自己的money,但当时因为暑假已经不多了,所以在寻找了大概一个星期后也没有找到合适的。最后这个挺不错的想法,也被我否定了。剩下的时间,就回到了自己的家乡,开始着手准备迎接我的大学生活。 但回家后的生活过的也分的颓废,每天大概一两点睡差不多11点起床然后吃了饭之后可能又是躺尸啊,因为天气比较热。离去大学报到的时间越来越近了,我开始去网上寻找大学需要准备一些什么东西,然后心满意足的买了各种各样自己认为可能会需要的东西,在2016年9月2号的时候,我拖着它们来到了属于我的大学,开始了我的大学生活。 大学生活的开始(大一上学期):军训 进入大学最开始的一件事可能就是军训了。我对军训的记忆就是累和放松,感到累,是因为每天要在特别热的环境下训练,不经意间,可能你还会收到教官的体罚。感到放松是因为每次休息或者教官带我们拉军歌大家一起玩,一起小游戏都会让你感觉特别的放松。 社团、学生会 军训后差不多就是学生会的招募了,当时面对各种各样的学生会自己感到很迷茫,对他们都没有太多的了解。他后来抱着自己想当一名志愿者,去帮助一下别人想法。经过了一轮面试,二轮面试,试用期这几个步骤终于成为了一名青协小干事。学生会给我留下的记忆就是温暖禾迷茫。会感到温暖欣慰,学生会是一个特别大的大家庭,每个人都是互相帮助来完成这个大家庭应该去完成的事情,而且在如果说某个人过生日,大家都会一起帮你过,常一起出去玩,一起做一些小活动,所以会感觉到温暖。感动迷茫,是因为很多事情自己之前都没有接触过功能无论是在对人或者对物都遇到了很多之前没遇到过的情景。刚加入学生会去死,学到了挺多认识到了许多许多新的朋友,知道了许多做事儿做人的方法。 专业方向加入学生会后不久学校或者学院特色的学长课堂开课了,当时我对学长课堂的各个方向基本都不太了解,在询问的几个学长之后。他们给出了我一些建议,最后选择了前端这个方向,能够选择到这个方向感觉也是人生对一种幸运,学长课堂在大二或者说大一下期仍然保留着的并不多,而就是其中一个,当时代前段的学长也不止一个到现‘在保留的却只有教我的学长还在带我们。在学长课堂的学习过程中学会的也不仅仅是一些专业知识。觉得自己更加去学会了去运用一些东西些论坛一些搜索引擎来解决问题的思想和方法。 大学课堂“自觉”是我对大学课堂的认识,在大学的课堂老司机的人不会在意你听课了,或者没有听课,老师也不会特别严苛的去检查你的任何关于学习的方面。 时间很快,差不多就到一个学期就这么过去了,一直踩着好运的我也以班级第二的成绩,哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈。 持续更新中···········]]></content>
<categories>
<category>生活</category>
</categories>
<tags>
<tag>分享</tag>
<tag>导航</tag>
</tags>
</entry>
<entry>
<title><![CDATA[Css之正方体]]></title>
<url>%2F2018%2F04%2F02%2Fcss-zft%2F</url>
<content type="text"><![CDATA[最近给大一的上课,想找一篇通俗点css制作立方体的文章给他们看,实在没找到最后索性就自己写一篇吧!!!第一步:大家需要有css3的基础,没有css3基础的可以先移步这里 css3第二步:先把下图牢牢地记住 第三步:搭建页面主体结构12345678910<div class="stage"> <div class="container"> <div class="face top">1</div> <div class="face back">2</div> <div class="face bottom">3</div> <div class="face front">4</div> <div class="face left">5</div> <div class="face right">6</div> </div> </div> 第四步 :编写基础css12345678910111213141516171819202122232425262728293031323334* { margin: 0; padding: 0; //清除默认样式 } .stage { position: relative; //让子元素相对父元素定位 margin: 300px 0 0 300px; perspective: 800px;//css3动画属性 width: 200px; height: 200px; } .container { width: 200px; height: 200px; position: absolute;//让自己可以相对父元素定位 transform-style: preserve-3d;//css3动画属性 } .face { width: 100%; height: 100%; position: absolute;//让自己可以相对父元素定位,并达到六个div重合效果 left: 0; top: 0; text-align: center;//字水平居中 line-height: 200px;//字垂直居中 font-size: 50px; color: #fff; border: 1px solid #ccc; opacity: 0.6;//设置透明度方便观察效果 background: #999; } 下面看看现在的效果 六个div重合在一起了 第五步:把每个div盒子定位到它应该在的地方1234567891011121314151617181920212223242526272829303132.top { color: aqua;//设置字体颜色方便观察 transform: rotateX(90deg) translateZ(100px); //这里就是重点了 现在回想刚才记住的坐标图 我们先绕X旋转90度 //这时候不仅div盒子变化了位置并且现在x y z三轴的方向也会随之改变!!!! //z变成了原来的y方向 y又变成原来的z方向 所以此时我们再向z移动100px就到了顶部 } .back { color: red; transform: translateZ(-100px); } .bottom { color: bisque; transform: rotateX(90deg) translateZ(-100px); } .front { color: palegreen; transform: translateZ(100px); } .left { color: rebeccapurple; transform: rotateY(90deg) translateZ(100px); } .right { color: darkorange; transform: rotateY(90deg) translateZ(-100px); } 看看现在的效果 如下图现在已经是一个正方体了但是却还不明显 我们让它总体沿着y轴旋转30° 在.container下加 transform:rotateY(35deg); 得到下图 最后我们加一个动画123456789@keyframes zhuan { from { transform: rotateX(0deg) rotateY(0deg); } to { transform: rotateX(360deg) rotateY(360deg); }} 就达到了如图结果:]]></content>
<categories>
<category>CSS</category>
</categories>
<tags>
<tag>分享</tag>
</tags>
</entry>
<entry>
<title><![CDATA[浅谈--forEach、for in、for of、for]]></title>
<url>%2F2018%2F03%2F29%2Fjs-%E5%BE%AA%E7%8E%AF%E5%8C%BA%E5%88%AB%2F</url>
<content type="text"><![CDATA[forEach从ES5开始 Javascript内置了forEach方法 用来遍历数组 对只能是数组!!! 12345 let arr = ['a', 'b', 'c', 'd']arr.forEach(function (val, index, arr) { // val是当前元素,index当前元素索引,arr当前数组 //this:window}) 划重点上面的forEach里的this => window 怎么改呢? 就是利用forEach的第二个参数了!!! 12345 let arr = ['a', 'b', 'c', 'd']arr.forEach(function (val, index, arr) { // val是当前元素,index当前元素索引,arr当前数组 //this =>obj},obj) 总结:写法简单了很多,但是也存在一个局限 就是你不能中断循环(使用break语句或使用return语句),而且只支持数组 for…infor-in循环实际是为循环”enumerable“对象而设计的,当然也可以用于数组,但是不推荐 12345let obj = {a: '1', b: '2', c: '3', d: '4'}for (let index in obj) { console.log(index) //遍历的实际上是对象的属性名称 a,b,c,d console.log(obj[index]) //这个才是属性对应的值1,2,3,4} 以上代码会出现的问题:1.index 值 会是字符串(String)类型2.循环不仅会遍历数组元素,还会遍历任意其他自定义添加的属性。 for-of 首先它是ES6中新增加的语法 遍历数组 1234 let arr = ['China', 'America', 'Korea']for (let o of arr) { console.log(o) //China, America, Korea} 它并不能循环一个普通对象1234let obj = {a: '1', b: '2', c: '3', d: '4'}for (let o of obj) { console.log(o) //Uncaught TypeError: obj[Symbol.iterator] is not a function} 但是可以循环一个拥有enumerable属性的对象。如果我们按对象所拥有的属性进行循环,可使用内置的Object.keys()方法1234let obj = {a: '1', b: '2', c: '3', d: '4'}for (let o of Object.keys(obj)) { console.log(o) // a,b,c,d} 如果我们按对象所拥有的属性值进行循环,可使用内置的Object.values()方法1234let obj = {a: '1', b: '2', c: '3', d: '4'}for (let o of Object.values(obj)) { console.log(o) // 1,2,3,4} 循环一个字符串1234let str = 'love'for (let o of str) { console.log(o) // l,o,v,e} 循环一个Map12345678910111213for (let [key, value] of iterable) { console.log(value);}// 1// 2// 3for (let entry of iterable) { console.log(entry);}// [a, 1]// [b, 2]// [c, 3] 循环一个Set12345678let iterable = new Set([1, 1, 2, 2, 3, 3]);for (let value of iterable) { console.log(value);}// 1// 2// 3 循环一个类型化数组1234567let iterable = new Uint8Array([0x00, 0xff]);for (let value of iterable) { console.log(value);}// 0// 255 总结:1.可以避免所有 for-in 循环的陷阱 2.不同于 forEach(),他可以使用 break, continue 和 return 3.for-of 循环不仅仅支持数组的遍历。同样适用于很多类似数组的对象 4.它也支持字符串的遍历 5.for-of 并不适用于处理原有的原生对象]]></content>
<categories>
<category>JavaScript</category>
</categories>
<tags>
<tag>分享</tag>
</tags>
</entry>
<entry>
<title><![CDATA[javaScript递归函数]]></title>
<url>%2F2018%2F03%2F27%2Fdigui%2F</url>
<content type="text"><![CDATA[首先什么是递归 递归是一项非常重要的编程技巧,函数通过它调用其本身。 —msdn文档介绍 举个例子,常用的乘阶。 12345function factorial(i) {flaseif (i === 1) return i;flasereturn i* factorial(i - 1);}console.log(factorial(5)); // 5*4*3*2*1 分几个步骤: 声明一个函数factorial,接受一个参数i。 判断i是否等于1,如果等于1则直接返回i。 如果i不等于1,则返回i * factorial(i - 1),再次调用函数本身。(如此如果严格可以判断i是否大于等于0) 然后函数就会重复2 - 3两个步骤,直至i减到1为止。 JavaScript执行上下文栈 大家可以看看这个教程,我认为很不错!地址 JavaScript执行顺序。 123456789101112var foo = functiom () {flaseconsole.log('foo1');}foo();var foo = functiom () {flaseconsole.log('foo2');}foo();//最后会打印出//foo1//foo2 解释一下这个为什么不会被覆盖12345678910//上面的代码写成这样就比较好理解var foo;foo = function() {flaseconsole.log('foo1')}foo()foo = function() {flaseconsole.log('foo2')}foo() 123456789101112131415function foo() { console.log('foo1');}foo(); // foo2function foo() { console.log('foo2');}foo(); // foo2 再解释一下这个!123456789101112function foo() { console.log('foo1');}function foo() { console.log('foo2');}foo(); // foo2foo(); // foo2 函数被提升之后第二个覆盖了第一个,这是JavaScript作用域提升。 JavaScript的可执行代码有三种,全局代码,函数代码,eval代码 当执行到一个函数的时候就会进行准备工作,叫做执行上下文。 原博客把执行上下文说的很清楚了,我理解了一部分。有兴趣可以点击上面的连接继续了解,继续讲递归。 尾调用根据上面的知识,以及以前的知识,我们都知道递归会消耗大量内存,之执行一个函数就压入上下文栈,直至递归结束才会释放,造成递归占用大量内存。 尾调用,是指函数内部的最后一个动作是函数调用,改调用的返回值,直接返回给函数。 1234function f (x) {flasereturn g(x)}// 尾调用 12345function f(x) {flasereturn g(x) - 1}// 非尾调用 用上面的上下文栈,来看第二个函数,函数f执行指挥返回一个g函数而g函数的结果需要f函数作用域内 - 1才是结果,导致引用的时候g函数入栈的时候会持有f函数的作用域,f得不到释放,一直等g函数结束之后才会被释放。 现在优化一下上面的递归 12345function factorial(i, res) {flaseif(i === 1) return res;flasereturn factorial(i-1, i*res)}console.log(factorial(4, 1)) 这样优化函数,保持返回的函数没有上个函数的引用,这样上个函数在入栈之后执行到return之后就会被释放,而不会和上面的递归一样等到最终结果才会被释放。(ps。JavaScript上下文栈,需要好好看看比较重要) ## javaScript]]></content>
<categories>
<category>JavaScript</category>
</categories>
<tags>
<tag>分享</tag>
</tags>
</entry>
<entry>
<title><![CDATA[占领未来的打包工具---Parcel(介绍)]]></title>
<url>%2F2018%2F03%2F19%2FpackParcelOne%2F</url>
<content type="text"><![CDATA[基本概况最近大家都在关注一个很流行的类似 webpack 的前端构建工具 Parcel。这个库刚出来没多久(截至目前发布几十天),但是很受欢迎,看下图就知道它到底有多火了。 这么火的东西我们怎么能不学呢?那么它到底火在哪儿?来看看我的示例分析(教程)吧!!! 官方介绍地址官方地址:https://parceljs.org/ GitHub地址:https://github.com/parcel-bundler/parcel Parcel VS Webpack听我扯一扯介绍这个库之前,我来说一下我个人觉得 webpack 的一些不好的地方(相对于 Parcel)。 1、需要写配置文件(webpack.config.js),可能每使用一个功能,比如加载图片或 css,都要添加配置,要维护配置文件,而 Parcel 不需要。 2、感觉编译或加载速度有些慢,特别是库多或项目复杂的时候,虽然有一些办法代码拆分的方法可以解决,比如 CommonsChunkPlugin 或 DLLPlugin 之类的,但这些方法有些复杂。 官方数据 打包速度 真的飞一般的感觉吧!!! 学习成本 webpack需要一定的时间去学习如何使用而 Parcel 有很多优点,可以不使用配置文件,也就是说你只管写代码,它会自动运行,很智能化,打个比方吧,比如在 webpack 中如果要处理 css,那得要安装和加载一个 css 的 loader,然后配置文件写上几行,可是 Parcel 不需要,直接用就行。Parcel 学习起来比较简单,基本上可以说 “不用学习”,只是使用就可以了。除此之外 模块热替换和代码拆分的功能,Parcel 也有,还有,如果要你用 Parcel 写一个 react 的运行环境,可能不需要配置任何内容,只要安装几个 react 的包就可以用起来了。 说了这么多,我还是要把官方对它的特性进行概括的图片放出来: 说到这里小伙伴们是不是和我当初一样心动了呢? 下一篇博客我们一起上手玩起来吧!!!]]></content>
<categories>
<category>打包工具</category>
</categories>
<tags>
<tag>分享</tag>
<tag>导航</tag>
</tags>
</entry>
<entry>
<title><![CDATA[markdown基础范例]]></title>
<url>%2F2018%2F03%2F13%2Fmarkdown%2F</url>
<content type="text"><![CDATA[你好,前端第一篇文章哦三级标题123# 你好,前端## 第一篇文章哦### 三级标题 列表1 列表2 a 次列表 b 此列表 列表三 12345- 列表1- 列表2 a 次列表 b 此列表- 列表三 博客导航 1[博客导航](http://www.aemple.top) 字体斜体字体加粗 1234![图片](/images/avatar.jpg)*字体斜体***字体加粗** <html></html> 12345678<html> <head> <title>我是标题</title> </head> <body> <h1>啦啦啦啦<h1> </body></html> 我是应用块哦 1>我是应用块哦 这些都经常用到希望小伙伴们加深记忆]]></content>
<categories>
<category>markdown</category>
</categories>
<tags>
<tag>分享</tag>
<tag>导航</tag>
</tags>
</entry>
<entry>
<title><![CDATA[Hello-Blog]]></title>
<url>%2F2018%2F03%2F13%2FhelloHexo%2F</url>
<content type="text"><![CDATA[第一次当然要hello啦,我是邓波,是你小粉丝。]]></content>
<categories>
<category>杂记</category>
</categories>
<tags>
<tag>分享</tag>
</tags>
</entry>
</search>