satarch怎么复制dnf角色名把脚本复制给多个角色

&figure&&img src=&/v2-649f14f6a804e92d99ed68cf_b.jpg& data-rawwidth=&1674& data-rawheight=&814& class=&origin_image zh-lightbox-thumb& width=&1674& data-original=&/v2-649f14f6a804e92d99ed68cf_r.jpg&&&/figure&&p&一、数据结构与算法基础&/p&&ul&&li&说一下几种常见的排序算法和分别的复杂度。&/li&&li&用Java写一个冒泡排序算法&/li&&li&描述一下链式存储结构。&/li&&li&如何遍历一棵二叉树?&/li&&li&倒排一个LinkedList。&/li&&li&用Java写一个递归遍历目录下面的所有文件。&/li&&/ul&&p&&br&&/p&&p&二、Java基础&/p&&ul&&li&接口与抽象类的区别?&/li&&li&Java中的异常有哪几类?分别怎么使用?&/li&&li&常用的集合类有哪些?比如List如何排序?&/li&&li&ArrayList和LinkedList内部的实现大致是怎样的?他们之间的区别和优缺点?&/li&&li&内存溢出是怎么回事?请举一个例子?&/li&&li&==和equals的区别?&/li&&li&hashCode方法的作用?&/li&&li&NIO是什么?适用于何种场景?&/li&&li&HashMap实现原理,如何保证HashMap的线程安全?&/li&&li&JVM内存结构,为什么需要GC?&/li&&li&NIO模型,select/epoll的区别,多路复用的原理&/li&&li&Java中一个字符占多少个字节,扩展再问int, long, double占多少字节&/li&&li&创建一个类的实例都有哪些办法?&/li&&li&final/finally/finalize的区别?&/li&&li&Session/Cookie的区别?&/li&&li&String/StringBuffer/StringBuilder的区别,扩展再问他们的实现?&/li&&li&Servlet的生命周期?&/li&&li&如何用Java分配一段连续的1G的内存空间?需要注意些什么?&/li&&li&Java有自己的内存回收机制,但为什么还存在内存泄露的问题呢?&/li&&li&什么是java序列化,如何实现java序列化?(写一个实例)?&/li&&li&String s = new String(&abc&);创建了几个 String Object?&/li&&/ul&&p&&br&&/p&&p&三、JVM&/p&&ul&&li&JVM堆的基本结构。&/li&&li&JVM的垃圾算法有哪几种?CMS垃圾回收的基本流程?&/li&&li&JVM有哪些常用启动参数可以调整,描述几个?&/li&&li&如何查看JVM的内存使用情况?&/li&&li&Java程序是否会内存溢出,内存泄露情况发生?举几个例子。&/li&&li&你常用的JVM配置和调优参数都有哪些?分别什么作用?&/li&&li&JVM的内存结构?&/li&&li&常用的GC策略,什么时候会触发YGC,什么时候触发FGC?&/li&&/ul&&p&&br&&/p&&p&四、多线程/并发&/p&&ul&&li&如何创建线程?如何保证线程安全?&/li&&li&如何实现一个线程安全的数据结构&/li&&li&如何避免死锁&/li&&li&Volatile关键字的作用?&/li&&li&HashMap在多线程环境下使用需要注意什么?为什么?&/li&&li&Java程序中启动一个线程是用run()还是start()?&/li&&li&什么是守护线程?有什么用?&/li&&li&什么是死锁?如何避免&/li&&li&线程和进程的差别是什么?&/li&&li&Java里面的Threadlocal是怎样实现的?&/li&&li&ConcurrentHashMap的实现原理是?&/li&&li&sleep和wait区别&/li&&li&notify和notifyAll区别&/li&&li&volatile关键字的作&/li&&li&ThreadLocal的作用与实现&/li&&li&两个线程如何串行执行&/li&&li&上下文切换是什么含义&/li&&li&可以运行时kill掉一个线程吗?&/li&&li&什么是条件锁、读写锁、自旋锁、可重入锁?&/li&&li&线程池ThreadPoolExecutor的实现原理?&/li&&/ul&&p&&br&&/p&&p&五、Linux使用与问题分析排查&/p&&ul&&li&使用两种命令创建一个文件?&/li&&li&硬链接和软链接的区别?&/li&&li&Linux常用命令有哪些?&/li&&li&怎么看一个Java线程的资源耗用?&/li&&li&Load过高的可能性有哪些?&/li&&li&/etc/hosts文件什么做用?&/li&&li&如何快速的将一个文本中所有“abc”替换为“xyz”?&/li&&li&如何在log文件中搜索找出error的日志?&/li&&li&发现磁盘空间不够,如何快速找出占用空间最大的文件?&/li&&li&Java服务端问题排查(OOM,CPU高,Load高,类冲突)&/li&&li&Java常用问题排查工具及用法(top, iostat, vmstat, sar, tcpdump, jvisualvm, jmap, jconsole)&/li&&li&Thread dump文件如何分析(Runnable,锁,代码栈,操作系统线程ID关联)&/li&&li&如何查看Java应用的线程信息?&/li&&/ul&&p&&br&&/p&&p&六、框架使用&/p&&ul&&li&描述一下Hibernate的三个状态?&/li&&li&Spring中Bean的生命周期。&/li&&li&SpringMVC或Struts处理请求的流程。&/li&&li&Spring AOP解决了什么问题?怎么实现的?&/li&&li&Spring事务的传播属性是怎么回事?它会影响什么?&/li&&li&Spring中BeanFactory和FactoryBean有什么区别?&/li&&li&Spring框架中IOC的原理是什么?&/li&&li&spring的依赖注入有哪几种方式&/li&&li&struts工作流程&/li&&li&用Spring如何实现一个切面?&/li&&li&Spring 如何实现数据库事务?&/li&&li&Hibernate对一二级缓存的使用,Lazy-Load的理解;&/li&&li&mybatis如何实现批量提交?&/li&&/ul&&p&&br&&/p&&p&七、数据库相关&/p&&ul&&li&MySQL InnoDB、Mysaim的特点?&/li&&li&乐观锁和悲观锁的区别?&/li&&li&数据库隔离级别是什么?有什么作用?&/li&&li&MySQL主备同步的基本原理。&/li&&li&select * from table t where size & 10
group by size order by size的sql语句执行顺序?&/li&&li&如何优化数据库性能(索引、分库分表、批量操作、分页算法、升级硬盘SSD、业务优化、主从部署)&/li&&li&SQL什么情况下不会使用索引(不包含,不等于,函数)&/li&&li&一般在什么字段上建索引(过滤数据最多的字段)&/li&&li&如何从一张表中查出name字段不包含“XYZ”的所有行?&/li&&li&MySQL,B+索引实现,行锁实现,SQL优化&/li&&li&Redis,RDB和AOF,如何做高可用、集群&/li&&li&如何解决高并发减库存问题&/li&&li&mysql存储引擎中索引的实现机制;&/li&&li&数据库事务的几种粒度;&/li&&li&行锁,表锁;乐观锁,悲观锁&/li&&/ul&&p&&br&&/p&&p&八、网络协议和网络编程&/p&&ul&&li&TCP建立连接的过程。&/li&&li&TCP断开连接的过程。&/li&&li&浏览器发生302跳转背后的逻辑?&/li&&li&HTTP协议的交互流程。HTTP和HTTPS的差异,SSL的交互流程?&/li&&li&Rest和Http什么关系? 大家都说Rest很轻量,你对Rest风格如何理解?&/li&&li&TCP的滑动窗口协议有什么用?讲讲原理。&/li&&li&HTTP协议都有哪些方法?&/li&&li&交换机和路由器的区别?&/li&&li&Socket交互的基本流程?&/li&&li&http协议(报文结构,断点续传,多线程下载,什么是长连接)&/li&&li&tcp协议(建连过程,慢启动,滑动窗口,七层模型)&/li&&li&webservice协议(wsdl/soap格式,与rest协议的区别)&/li&&li&NIO的好处,Netty线程模型,什么是零拷贝&/li&&/ul&&p&&br&&/p&&p&九、Redis等缓存系统/中间件/NoSQL/一致性Hash等&/p&&ul&&li&列举一个常用的Redis客户端的并发模型。&/li&&li&HBase如何实现模糊查询?&/li&&li&列举一个常用的消息中间件,如果消息要保序如何实现?&/li&&li&如何实现一个Hashtable?你的设计如何考虑Hash冲突?如何优化?&/li&&li&分布式缓存,一致性hash&/li&&li&LRU算法,slab分配,如何减少内存碎片&/li&&li&如何解决缓存单机热点问题&/li&&li&什么是布隆过滤器,其实现原理是? False positive指的是?&/li&&li&memcache与redis的区别&/li&&li&zookeeper有什么功能,选举算法如何进行&/li&&li&map/reduce过程,如何用map/reduce实现两个数据源的联合统计&/li&&/ul&&p&&br&&/p&&p&十、设计模式与重构&/p&&ul&&li&你能举例几个常见的设计模式&/li&&li&你在设计一个工厂的包的时候会遵循哪些原则?&/li&&li&你能列举一个使用了Visitor/Decorator模式的开源项目/库吗?&/li&&li&你在编码时最常用的设计模式有哪些?在什么场景下用?&/li&&li&如何实现一个单例?&/li&&li&代理模式(动态代理)&/li&&li&单例模式(懒汉模式,恶汉模式,并发初始化如何解决,volatile与lock的使用)&/li&&li&JDK源码里面都有些什么让你印象深刻的设计模式使用,举例看看?&/li&&/ul&
一、数据结构与算法基础说一下几种常见的排序算法和分别的复杂度。用Java写一个冒泡排序算法描述一下链式存储结构。如何遍历一棵二叉树?倒排一个LinkedList。用Java写一个递归遍历目录下面的所有文件。 二、Java基础接口与抽象类的区别?Java中的异常有哪…
&figure&&img src=&/v2-91d2fa7ee8c0b97daa69eb_b.jpg& data-rawwidth=&1400& data-rawheight=&751& class=&origin_image zh-lightbox-thumb& width=&1400& data-original=&/v2-91d2fa7ee8c0b97daa69eb_r.jpg&&&/figure&&blockquote&原文链接:&a href=&/?target=https%3A///%40peterxjang/modern-javascript-explained-for-dinosaurs-f695e9747b70& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Modern JavaScript Explained For Dinosaurs&i class=&icon-external&&&/i&&/a&&br&&br&作者:&a href=&/?target=https%3A///%40peterxjang& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Peter&i class=&icon-external&&&/i&&/a& &a href=&/?target=https%3A///%40peterxjang& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Jang&i class=&icon-external&&&/i&&/a&&br&&br&译者:&a href=&/people/Murphy-T& class=&internal&&Murphy&/a&&br&&br&转载请注明出处&/blockquote&&figure&&img src=&/v2-93dd4b227f07cb132dccd05_b.jpg& data-size=&normal& data-rawwidth=&1498& data-rawheight=&974& class=&origin_image zh-lightbox-thumb& width=&1498& data-original=&/v2-93dd4b227f07cb132dccd05_r.jpg&&&figcaption&Images from Dinosaur Comics by Ryan North&/figcaption&&/figure&&p&有时候入门没入好,学习起现代的 JavaScript 开发还是颇有难度的。生态系统太日新月异以至于让人难以理解不同工具的出现究竟是为了解决什么问题。我从 1988 年开始编程,但直至 2014 年才开始认真地学习起 JavaScript。记得那时第一次遇到 &a href=&/?target=http%3A//browserify.org/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Browserify&i class=&icon-external&&&/i&&/a& 时看着它的标语:&/p&&blockquote&Browserify lets you require('modules') in the browser by bundling up all of your dependencies.&/blockquote&&p&这句话里的单词我一个都看不懂,不知道为什么这个东西会对自己这样一个开发者能有用。&/p&&p&&br&&/p&&p&本篇文章的目标便是提供一个有关 JavaScript 工具进化的历史视角,看看它们是怎么一步一步演变到如今 -- 2017 年的这个样子的。开始的开始,我们将像最原始的恐龙家族一样建一个网站 -- 不依赖任何工具,就用最简单的 HTML 和 JavaScript。然后再循序渐进引入不同的工具,看看每个工具分别解决了什么问题。开始吧~&br&&/p&&h2&&b&“守旧派”使用 JavaScript 的方法&/b&&/h2&&p&首先,来像“守旧派”一样使用 HTML 和
JavaScript 来建个网站 -- 手动下载和内联文件。像这样~&/p&&div class=&highlight&&&pre&&code class=&language-html&&&span&&/span&&span class=&c&&&!-- index.html --&&/span&
&span class=&cp&&&!DOCTYPE html&&/span&
&span class=&p&&&&/span&&span class=&nt&&html&/span& &span class=&na&&lang&/span&&span class=&o&&=&/span&&span class=&s&&&en&&/span&&span class=&p&&&&/span&
&span class=&p&&&&/span&&span class=&nt&&head&/span&&span class=&p&&&&/span&
&span class=&p&&&&/span&&span class=&nt&&meta&/span& &span class=&na&&charset&/span&&span class=&o&&=&/span&&span class=&s&&&UTF-8&&/span&&span class=&p&&&&/span&
&span class=&p&&&&/span&&span class=&nt&&title&/span&&span class=&p&&&&/span&JavaScript Example&span class=&p&&&/&/span&&span class=&nt&&title&/span&&span class=&p&&&&/span&
&span class=&p&&&&/span&&span class=&nt&&script&/span& &span class=&na&&src&/span&&span class=&o&&=&/span&&span class=&s&&&index.js&&/span&&span class=&p&&&&/&/span&&span class=&nt&&script&/span&&span class=&p&&&&/span&
&span class=&p&&&/&/span&&span class=&nt&&head&/span&&span class=&p&&&&/span&
&span class=&p&&&&/span&&span class=&nt&&body&/span&&span class=&p&&&&/span&
&span class=&p&&&&/span&&span class=&nt&&h1&/span&&span class=&p&&&&/span&Hello from HTML!&span class=&p&&&/&/span&&span class=&nt&&h1&/span&&span class=&p&&&&/span&
&span class=&p&&&/&/span&&span class=&nt&&body&/span&&span class=&p&&&&/span&
&span class=&p&&&/&/span&&span class=&nt&&html&/span&&span class=&p&&&&/span&
&/code&&/pre&&/div&&p&&code&&script src=&index.js&&&/script&&/code& 这行指的是引入在同一目录下的一个叫做 &code&&b&index.js&/b&&/code& 的单独文件:&/p&&div class=&highlight&&&pre&&code class=&language-js&&&span&&/span&&span class=&c1&&// index.js&/span&
&span class=&nx&&console&/span&&span class=&p&&.&/span&&span class=&nx&&log&/span&&span class=&p&&(&/span&&span class=&s2&&&Hello from JavaScript!&&/span&&span class=&p&&);&/span&
&/code&&/pre&&/div&&p&这几乎就是你建站需要的一切了~ 现在呢,你想加进去一个其他人写的库,例如 &a href=&/?target=http%3A///& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&moment.js&i class=&icon-external&&&/i&&/a& (一个以可读性更好的方式格式化日期的库)。例如,你可以像这样使用一个 &code&moment&/code& 函数:&/p&&div class=&highlight&&&pre&&code class=&language-js&&&span&&/span&&span class=&nx&&moment&/span&&span class=&p&&().&/span&&span class=&nx&&startOf&/span&&span class=&p&&(&/span&&span class=&s1&&'day'&/span&&span class=&p&&).&/span&&span class=&nx&&fromNow&/span&&span class=&p&&();&/span& &span class=&c1&&// 20 hours ago&/span&
&/code&&/pre&&/div&&p&但这是假设你已经在网站中包括了 moment.js 的前提下!在 moment.js 的&a href=&/?target=http%3A///& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&主页&i class=&icon-external&&&/i&&/a&上,你可以看到如下的指南:&/p&&figure&&img src=&/v2-d984fe4fa1db88b105a5dc_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&1590& data-rawheight=&536& class=&origin_image zh-lightbox-thumb& width=&1590& data-original=&/v2-d984fe4fa1db88b105a5dc_r.jpg&&&/figure&&p&Hmm,在 &b&Install &/b&这部分右边貌似有很多东西啊!先无视它 -- 我们可以下载 &b&&code&moment.min.js&/code&&/b&
文件到同级目录中,并在 &b&&code&index.html&/code&&/b& 中引入:&/p&&div class=&highlight&&&pre&&code class=&language-html&&&span&&/span&&span class=&c&&&!-- index.html --&&/span&
&span class=&cp&&&!DOCTYPE html&&/span&
&span class=&p&&&&/span&&span class=&nt&&html&/span& &span class=&na&&lang&/span&&span class=&o&&=&/span&&span class=&s&&&en&&/span&&span class=&p&&&&/span&
&span class=&p&&&&/span&&span class=&nt&&head&/span&&span class=&p&&&&/span&
&span class=&p&&&&/span&&span class=&nt&&meta&/span& &span class=&na&&charset&/span&&span class=&o&&=&/span&&span class=&s&&&UTF-8&&/span&&span class=&p&&&&/span&
&span class=&p&&&&/span&&span class=&nt&&title&/span&&span class=&p&&&&/span&Example&span class=&p&&&/&/span&&span class=&nt&&title&/span&&span class=&p&&&&/span&
&span class=&p&&&&/span&&span class=&nt&&link&/span& &span class=&na&&rel&/span&&span class=&o&&=&/span&&span class=&s&&&stylesheet&&/span& &span class=&na&&href&/span&&span class=&o&&=&/span&&span class=&s&&&index.css&&/span&&span class=&p&&&&/span&
&span class=&p&&&&/span&&span class=&nt&&script&/span& &span class=&na&&src&/span&&span class=&o&&=&/span&&span class=&s&&&moment.min.js&&/span&&span class=&p&&&&/&/span&&span class=&nt&&script&/span&&span class=&p&&&&/span&
&span class=&p&&&&/span&&span class=&nt&&script&/span& &span class=&na&&src&/span&&span class=&o&&=&/span&&span class=&s&&&index.js&&/span&&span class=&p&&&&/&/span&&span class=&nt&&script&/span&&span class=&p&&&&/span&
&span class=&p&&&/&/span&&span class=&nt&&head&/span&&span class=&p&&&&/span&
&span class=&p&&&&/span&&span class=&nt&&body&/span&&span class=&p&&&&/span&
&span class=&p&&&&/span&&span class=&nt&&h1&/span&&span class=&p&&&&/span&Hello from HTML!&span class=&p&&&/&/span&&span class=&nt&&h1&/span&&span class=&p&&&&/span&
&span class=&p&&&/&/span&&span class=&nt&&body&/span&&span class=&p&&&&/span&
&span class=&p&&&/&/span&&span class=&nt&&html&/span&&span class=&p&&&&/span&
&/code&&/pre&&/div&&p&注意 &code&&b&moment.min.js&/b&&/code& 会在 &code&&b&index.js&/b&&/code& 之前下载完成,所以你可以在 &code&&b&index.js&/b&&/code& 中像这样使用 &code&moment&/code& 函数:&/p&&div class=&highlight&&&pre&&code class=&language-js&&&span&&/span&&span class=&c1&&// index.js&/span&
&span class=&nx&&console&/span&&span class=&p&&.&/span&&span class=&nx&&log&/span&&span class=&p&&(&/span&&span class=&s2&&&Hello from JavaScript!&&/span&&span class=&p&&);&/span&
&span class=&nx&&console&/span&&span class=&p&&.&/span&&span class=&nx&&log&/span&&span class=&p&&(&/span&&span class=&nx&&moment&/span&&span class=&p&&().&/span&&span class=&nx&&startOf&/span&&span class=&p&&(&/span&&span class=&s1&&'day'&/span&&span class=&p&&).&/span&&span class=&nx&&fromNow&/span&&span class=&p&&());&/span&
&/code&&/pre&&/div&&p&这就是我们怎么利用 JavaScript 库建站! 这种方式的好处是非常容易理解。然而坏处是当库的作者更新时,每次寻找和下载新的版本就会很烦。&br&&/p&&h2&&b&使用 JavaScript 包管理工具(npm)&/b&&/h2&&p&大约从 2010 年开始,几个相互竞争的 JavaScript 包管理工具开始出现,来帮人们从中心仓库中自动完成下载和升级的流程。&a href=&/?target=https%3A//bower.io/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Bower&i class=&icon-external&&&/i&&/a& 在 2013 年可以说是最流行的一个了,但最终在 2015 年左右还是被 &a href=&/?target=https%3A///& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&npm&i class=&icon-external&&&/i&&/a& 打败了。(值得一提的是,大约从 2016 年开始,&a href=&/?target=https%3A///en/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&yarn&i class=&icon-external&&&/i&&/a& 作为一个可选的 npm
替代开始占据一席之地,但 npm 仍占上风。)&/p&&p&注意到,npm 作为一个包管理工具,最开始是专门为 &a href=&/?target=https%3A//nodejs.org/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&node.js&i class=&icon-external&&&/i&&/a& -- 一个运行在服务器端的 JavaScript 运行时 (runtime) 而准备的,并不是前端。所以选择它作为在浏览器中运行 JavaScript 的前端包管理工具似乎有些奇怪。&/p&&blockquote&&b&注意: &/b&使用包管理工具通常涉及命令行的使用,在以前这并不是一个前端开发者所必须的技能。如果你从未使用过,可以阅读&a href=&/?target=https%3A///command-line-tutorial& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&这篇教程&i class=&icon-external&&&/i&&/a&概览一番。无论如何,知道如何使用命令行也是现代 JavaScript 开发的一部分(这也是进入其他领域重要的一步)。 &/blockquote&&p&让我们看看怎么使用 npm 来自动完成 moment.js 的安装。如果你安装了 node.js,npm 也就已经随之安装了,你可以操纵你的命令行进入 &b&&code&index.html&/code&&/b& 目录下并输入:&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&$ npm init
&/code&&/pre&&/div&&p&这将会引导你填写几个问题(默认值也可以,你可以一直敲 “Enter” 键)并生成一个叫做 &code&&b&package.json&/b&&/code&
的文件,大概长这样:&/p&&div class=&highlight&&&pre&&code class=&language-json&&&span&&/span&&span class=&p&&{&/span&
&span class=&nt&&&name&&/span&&span class=&p&&:&/span& &span class=&s2&&&your-project-name&&/span&&span class=&p&&,&/span&
&span class=&nt&&&version&&/span&&span class=&p&&:&/span& &span class=&s2&&&1.0.0&&/span&&span class=&p&&,&/span&
&span class=&nt&&&description&&/span&&span class=&p&&:&/span& &span class=&s2&&&&&/span&&span class=&p&&,&/span&
&span class=&nt&&&main&&/span&&span class=&p&&:&/span& &span class=&s2&&&index.js&&/span&&span class=&p&&,&/span&
&span class=&nt&&&scripts&&/span&&span class=&p&&:&/span& &span class=&p&&{&/span&
&span class=&nt&&&test&&/span&&span class=&p&&:&/span& &span class=&s2&&&echo \&Error: no test specified\& && exit 1&&/span&
&span class=&p&&},&/span&
&span class=&nt&&&author&&/span&&span class=&p&&:&/span& &span class=&s2&&&&&/span&&span class=&p&&,&/span&
&span class=&nt&&&license&&/span&&span class=&p&&:&/span& &span class=&s2&&&ISC&&/span&
&span class=&p&&}&/span&
&/code&&/pre&&/div&&p&要安装 monment.js 包的话,我们可以按照主页上介绍的 npm 安装方法在命令行敲下:&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&$ npm install moment --save
&/code&&/pre&&/div&&p&这行命令做了两件事 -- 第一,它从 &a href=&/?target=https%3A///moment/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&moment.js package&i class=&icon-external&&&/i&&/a& 下载了所有代码到一个叫 &code&node_modules&/code& 的文件夹中。第二,它自动修改了 &code&&b&package.json&/b&&/code& 文件来追踪 moment.js 作为项目的依赖:&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&{
&name&: &modern-javascript-example&,
&version&: &1.0.0&,
&description&: &&,
&main&: &index.js&,
&scripts&: {
&test&: &echo \&Error: no test specified\& && exit 1&
&author&: &&,
&license&: &ISC&,
&dependencies&: { // 手动加粗
&moment&: &^2.19.1&
&/code&&/pre&&/div&&p&这在和他人共享项目时非常有用 -- 并不需要直接共享 &code&&b&node_modules&/b&&/code& 文件夹(可能会非常大),你只需要共享你的 &code&&b&package.json&/b&&/code& 文件,其他开发者便可以使用命令 &code&npm install&/code& 自动安装项目所需要的包。&/p&&p&&br&&/p&&p&现在,我们不再需要从网站上手动下载 moment.js 了,我们可以使用 npm 自动下载和更新。然后看一下 &code&&b&node_modules&/b&&/code& 内部,发现 &code&&b&moment.min.js&/b&&/code& 文件位于 &code&&b&node_modules/moment/min&/b&&/code& 目录。所以可以把 npm 下载的版本的 &code&&b&moment.min.js&/b&&/code& 像这样引入 &code&&b&index.html&/b&&/code& 文件:&/p&&p&&br&&/p&&div class=&highlight&&&pre&&code class=&language-html&&&span&&/span&&span class=&c&&&!-- index.html --&&/span&
&span class=&cp&&&!DOCTYPE html&&/span&
&span class=&p&&&&/span&&span class=&nt&&html&/span& &span class=&na&&lang&/span&&span class=&o&&=&/span&&span class=&s&&&en&&/span&&span class=&p&&&&/span&
&span class=&p&&&&/span&&span class=&nt&&head&/span&&span class=&p&&&&/span&
&span class=&p&&&&/span&&span class=&nt&&meta&/span& &span class=&na&&charset&/span&&span class=&o&&=&/span&&span class=&s&&&UTF-8&&/span&&span class=&p&&&&/span&
&span class=&p&&&&/span&&span class=&nt&&title&/span&&span class=&p&&&&/span&JavaScript Example&span class=&p&&&/&/span&&span class=&nt&&title&/span&&span class=&p&&&&/span&
&span class=&c&&&!-- 手动加粗下一行 --&&/span&
&span class=&p&&&&/span&&span class=&nt&&script&/span& &span class=&na&&src&/span&&span class=&o&&=&/span&&span class=&s&&&node_modules/moment/min/moment.min.js&&/span&&span class=&p&&&&/&/span&&span class=&nt&&script&/span&&span class=&p&&&&/span&
&span class=&p&&&&/span&&span class=&nt&&script&/span& &span class=&na&&src&/span&&span class=&o&&=&/span&&span class=&s&&&index.js&&/span&&span class=&p&&&&/&/span&&span class=&nt&&script&/span&&span class=&p&&&&/span&
&span class=&p&&&/&/span&&span class=&nt&&head&/span&&span class=&p&&&&/span&
&span class=&p&&&&/span&&span class=&nt&&body&/span&&span class=&p&&&&/span&
&span class=&p&&&&/span&&span class=&nt&&h1&/span&&span class=&p&&&&/span&Hello from HTML!&span class=&p&&&/&/span&&span class=&nt&&h1&/span&&span class=&p&&&&/span&
&span class=&p&&&/&/span&&span class=&nt&&body&/span&&span class=&p&&&&/span&
&span class=&p&&&/&/span&&span class=&nt&&html&/span&&span class=&p&&&&/span&
&/code&&/pre&&/div&&p&所以好消息是我们现在可以通过命令行使用 npm 下载和更新包了。坏消息是我们还得搜寻整个 &code&&b&node_modules&/b&&/code& 目录来定位每个包的路径再手动添加到我们 HTML 文件中。实在太太不方便了,所以下一步,来看看怎么把这个过程也自动化起来吧。&/p&&figure&&img src=&/v2-6848f0fbd2e9320aacde7d3_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&793& data-rawheight=&532& class=&origin_image zh-lightbox-thumb& width=&793& data-original=&/v2-6848f0fbd2e9320aacde7d3_r.jpg&&&/figure&&h2&&b&使用 JavaScript 模块打包工具(webpack)&/b&&/h2&&p&大多数编程语言都会提供从一个文件导入另一个文件代码的机制。然而 JavaScript 最初设计时并没有这个特性,因为 JavaScript 原本是为了在浏览器端运行而设计的,并没有权限获取计算机客户端的文件系统(安全考虑)。所以很长一段时间以来,组织多个文件的 JavaScript 代码就是把每个文件下载下来,变量是全局共享的。 &/p&&p&这实际上和我们刚才对 moment.js 的所做的并无二致 -- 把整个的 &code&&b&moment.min.js&/b&&/code& 文件下载到 HTML 中,定义了一个全局变量 &code&moment&/code&,对于所有在 &code&&b&moment.min.js&/b&&/code& 之后下载的文件都可用(无论是否真的需要它)。
&/p&&p&2009 年,一个叫做 CommonJS 的项目兴起,目标是规范 JavaScript 在浏览器之外的生态系统。CommonJS 中很大的一部分便是对模块系统的规范,允许 JavaScript 像大多数编程语言那样允许导入导出代码而不用借助于全局变量。最知名的对 CommonJS 模块规范的实现便是 node.js。(译者注:Node 在实现中也并非完全按照规范,而是对模块规范进行了一定取舍,同时增加了一些自身需要的特性。)&/p&&figure&&img src=&/v2-d3e4fab74c44fcce0395_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&424& data-rawheight=&274& class=&origin_image zh-lightbox-thumb& width=&424& data-original=&/v2-d3e4fab74c44fcce0395_r.jpg&&&/figure&&p&如前所述,node.js 是为 JavaScript 设计在服务器端的一个运行时。假如让我们用 node.js 模块来重写前面的例子的话,不需要把整个 &b&&code&monment.min.js&/code&&/b& 文件用 HTML 标签下载下来,你可以直接在 JavaScript 文件中这样加载:&/p&&div class=&highlight&&&pre&&code class=&language-js&&&span&&/span&&span class=&c1&&// index.js&/span&
&span class=&kd&&var&/span& &span class=&nx&&moment&/span& &span class=&o&&=&/span& &span class=&nx&&require&/span&&span class=&p&&(&/span&&span class=&s1&&'moment'&/span&&span class=&p&&);&/span&
&span class=&nx&&console&/span&&span class=&p&&.&/span&&span class=&nx&&log&/span&&span class=&p&&(&/span&&span class=&s2&&&Hello from JavaScript!&&/span&&span class=&p&&);&/span&
&span class=&nx&&console&/span&&span class=&p&&.&/span&&span class=&nx&&log&/span&&span class=&p&&(&/span&&span class=&nx&&moment&/span&&span class=&p&&().&/span&&span class=&nx&&startOf&/span&&span class=&p&&(&/span&&span class=&s1&&'day'&/span&&span class=&p&&).&/span&&span class=&nx&&fromNow&/span&&span class=&p&&());&/span&
&/code&&/pre&&/div&&p&然而,这是在 node.js 中才起作用的模块加载方法, node.js 作为一个服务器端语言,有权限访问计算机的文件系统,因此工作良好。Node.js 还知道每个 npm 模块的路径,所以我们不需要写上 &code&require('./node_modules/moment/min/moment.min.js)&/code&,而可以直接写 &code&require('moment')&/code&-- 是不是很贴心~&/p&&p&对 node.js 来说这一切都很棒,但是如果你真的把上面的代码运行在浏览器中的话,你会得到一个报错 &code&&b&require&/b& is not defined&/code&。浏览器没有对文件系统的权限,这就意味着用这种方式加载模块很难搞 -- 文件必须被动态地加载,或者同步地加载(减慢执行速度)或者异步地加载(不能保证时间顺序)。&/p&&p&这就是模块打包器随之出现的原因。JavaScript 模块打包器是一个能在代码构建过程(有文件系统权限)绕过这个问题并打包生产出兼容于浏览器的生产版本(不再需要有文件系统权限)的工具。在这个例子中,我们需要一个模块打包器,找到所有 &code&require&/code& 语句(它在浏览器端的 JavaScript 中是非法的)并把它们替换成想 require 的文件实际的内容。最终结果是一个打包后的 JavaScript 文件(没有 require 语句)!&/p&&p&曾经最流行的模块打包器是 &a href=&/?target=http%3A//browserify.org/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Browserify&i class=&icon-external&&&/i&&/a&,于 2011 年发布,它倡导在前端使用 node.js 风格的 require 语句(这对 npm 成为前端包管理工具的选择是至关重要的)。2015 年左右,&a href=&/?target=https%3A//webpack.github.io/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&webpack&i class=&icon-external&&&/i&&/a& 最终成为更为广泛使用的包管理器(&a href=&/?target=https%3A//reactjs.org/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&React&i class=&icon-external&&&/i&&/a& 的流行大大推动了这一进程,它充分利用了 webpack 的各种特性)。&/p&&p&来看一下怎么用 webpack 让上面的 &code&require('moment')&/code& 的例子在浏览器中起作用吧。首先,我们需要把 webpack 安装到项目中。Webpack 本身也是一个 npm 包,所以可以使用命令行愉快地安装:&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&$ npm install webpack --save-dev
&/code&&/pre&&/div&&p&注意到 &code&--save-dev&/code& 参数 -- 把它作为开发环境的依赖,而不是生产环境,因为并不需要把它放到服务器上。你可以在 &code&&b&package.json&/b&&/code& 文件中看到对应的更改,已经自动更新如下: &/p&&div class=&highlight&&&pre&&code class=&language-json&&&span&&/span&&span class=&p&&{&/span&
&span class=&nt&&&name&&/span&&span class=&p&&:&/span& &span class=&s2&&&modern-javascript-example&&/span&&span class=&p&&,&/span&
&span class=&nt&&&version&&/span&&span class=&p&&:&/span& &span class=&s2&&&1.0.0&&/span&&span class=&p&&,&/span&
&span class=&nt&&&description&&/span&&span class=&p&&:&/span& &span class=&s2&&&&&/span&&span class=&p&&,&/span&
&span class=&nt&&&main&&/span&&span class=&p&&:&/span& &span class=&s2&&&index.js&&/span&&span class=&p&&,&/span&
&span class=&nt&&&scripts&&/span&&span class=&p&&:&/span& &span class=&p&&{&/span&
&span class=&nt&&&test&&/span&&span class=&p&&:&/span& &span class=&s2&&&echo \&Error: no test specified\& && exit 1&&/span&
&span class=&p&&},&/span&
&span class=&nt&&&author&&/span&&span class=&p&&:&/span& &span class=&s2&&&&&/span&&span class=&p&&,&/span&
&span class=&nt&&&license&&/span&&span class=&p&&:&/span& &span class=&s2&&&ISC&&/span&&span class=&p&&,&/span&
&span class=&nt&&&dependencies&&/span&&span class=&p&&:&/span& &span class=&p&&{&/span&
&span class=&nt&&&moment&&/span&&span class=&p&&:&/span& &span class=&s2&&&^2.19.1&&/span&
&span class=&p&&},&/span&
&span class=&nt&&&devDependencies&&/span&&span class=&p&&:&/span& &span class=&p&&{&/span& &span class=&err&&//&/span& &span class=&err&&手动加粗&/span&
&span class=&nt&&&webpack&&/span&&span class=&p&&:&/span& &span class=&s2&&&^3.7.1&&/span&
&span class=&p&&}&/span&
&span class=&p&&}&/span&
&/code&&/pre&&/div&&p&现在 webpack 作为一个 &code&node_modules&/code& 中的包已经安装好了,可以在命令行中像这样使用 &code&webpack&/code&:&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&$ ./node_modules/.bin/webpack index.js bundle.js
&/code&&/pre&&/div&&p&这行命令将会运行位于 &code&&b&node_modules&/b&&/code& 中的 webpack 工具,它将从 &code&&b&index.js&/b&&/code& 开始,找到所有&code&require&/code& 语句,把它们替换成合适的代码并输出一个单文件叫 &code&&b&bundle.js&/b&&/code& 。这意味着我们在浏览器中不再需要 &code&&b&index.js&/b&&/code&,因为它包含非法的 require 语句。而是使用输出的 &code&&b&bundle.js&/b&&/code& 文件,因此我们应当修改 &code&&b&index.html&/b&&/code& 文件 :&/p&&div class=&highlight&&&pre&&code class=&language-html&&&span&&/span&&span class=&c&&&!-- index.html --&&/span&
&span class=&cp&&&!DOCTYPE html&&/span&
&span class=&p&&&&/span&&span class=&nt&&html&/span& &span class=&na&&lang&/span&&span class=&o&&=&/span&&span class=&s&&&en&&/span&&span class=&p&&&&/span&
&span class=&p&&&&/span&&span class=&nt&&head&/span&&span class=&p&&&&/span&
&span class=&p&&&&/span&&span class=&nt&&meta&/span& &span class=&na&&charset&/span&&span class=&o&&=&/span&&span class=&s&&&UTF-8&&/span&&span class=&p&&&&/span&
&span class=&p&&&&/span&&span class=&nt&&title&/span&&span class=&p&&&&/span&JavaScript Example&span class=&p&&&/&/span&&span class=&nt&&title&/span&&span class=&p&&&&/span&
&span class=&c&&&!-- 手动加粗下一行 --&&/span&
&span class=&p&&&&/span&&span class=&nt&&script&/span& &span class=&na&&src&/span&&span class=&o&&=&/span&&span class=&s&&&bundle.js&&/span&&span class=&p&&&&/&/span&&span class=&nt&&script&/span&&span class=&p&&&&/span&
&span class=&p&&&/&/span&&span class=&nt&&head&/span&&span class=&p&&&&/span&
&span class=&p&&&&/span&&span class=&nt&&body&/span&&span class=&p&&&&/span&
&span class=&p&&&&/span&&span class=&nt&&h1&/span&&span class=&p&&&&/span&Hello from HTML!&span class=&p&&&/&/span&&span class=&nt&&h1&/span&&span class=&p&&&&/span&
&span class=&p&&&/&/span&&span class=&nt&&body&/span&&span class=&p&&&&/span&
&span class=&p&&&/&/span&&span class=&nt&&html&/span&&span class=&p&&&&/span&
&/code&&/pre&&/div&&p&刷新一下浏览器,一切又都像以前一样可以正常工作啦!&/p&&p&注意到每当我们修改 &code&&b&index.js&/b&&/code& 后都要运行 webpack 一长串的命令。好烦呀,而且当我们使用到 webpack 更高级的特性时就更烦了(例如使用 &a href=&/?target=https%3A//webpack.js.org/guides/development/%23using-source-maps& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&generating source maps&i class=&icon-external&&&/i&&/a& 帮我们从编译后的代码调试原始的代码)。Webpack 可以从项目文件的根目录中的一个叫做 &code&&b&webpack.config.js&/b&&/code&的配置文件中读取相应设置,在我们的栗子中,差不多应该配置成这样:&/p&&div class=&highlight&&&pre&&code class=&language-js&&&span&&/span&&span class=&c1&&// webpack.config.js&/span&
&span class=&nx&&module&/span&&span class=&p&&.&/span&&span class=&nx&&exports&/span& &span class=&o&&=&/span& &span class=&p&&{&/span&
&span class=&nx&&entry&/span&&span class=&o&&:&/span& &span class=&s1&&'./index.js'&/span&&span class=&p&&,&/span&
&span class=&nx&&output&/span&&span class=&o&&:&/span& &span class=&p&&{&/span&
&span class=&nx&&filename&/span&&span class=&o&&:&/span& &span class=&s1&&'bundle.js'&/span&
&span class=&p&&}&/span&
&span class=&p&&};&/span&
&/code&&/pre&&/div&&p&这样每次我们改变 &code&&b&index.js&/b&&/code& 后,就可以在命令行中运行:&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&$ ./node_modules/.bin/webpack
&/code&&/pre&&/div&&p&我们不需要再特意指出 &code&&b&index.js&/b&&/code& 和 &code&&b&bundle.js&/b&&/code& 选项,因为 webpack 已经从 &code&&b&webpack.config.js&/b&&/code& 中加载得到了。比刚才好了一点,但每次修改代码还要敲命令还是很烦 -- 稍后我们会让这个过程再顺利些~&/p&&p&纵观一下,虽然可能看起来变化不大,但这个流程实际上取得了很大的进步。我们不再需要使用额外的标签加载全局变量。任何新的 JavaScript 库都可以使用 &code&require&/code& 语句在 JavaScript 文件中引入,而不是在 HTML里加 &code&&script&&/code& 标签。而且打包后的单 JavaScript 文件对性能提升是很大的优势。而且现在既然有了代码的构建过程,我们还可以在我们开发的工作流中加入一些更强大的特性! &/p&&figure&&img src=&/v2-25af997a19310b7bea747db_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&1083& data-rawheight=&541& class=&origin_image zh-lightbox-thumb& width=&1083& data-original=&/v2-25af997a19310b7bea747db_r.jpg&&&/figure&&p&&br&&/p&&h2&&b&使用新的语言特性并编译代码(babel)&/b&&/h2&&p&编译(transpiling)意味着把代码从一种语言转换成另一种相似的语言。这在前端的发展中是很重要的一部分 -- 浏览器添加新的特性很慢,带有实验中特性的新语言相继创造出来再编译成能在浏览器中兼容的语言。&/p&&p&对 CSS ,举几个来说, &a href=&/?target=http%3A///& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Sass&i class=&icon-external&&&/i&&/a&, &a href=&/?target=http%3A//lesscss.org/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Less&i class=&icon-external&&&/i&&/a&,
&a href=&/?target=http%3A///& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Stylus&i class=&icon-external&&&/i&&/a&。对 JavaScript 来说,曾经一度最流行的是 &a href=&/?target=http%3A//coffeescript.org/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&CoffeeScript&i class=&icon-external&&&/i&&/a& (大约在 2010 年发布),而现在大多数人会使用
&a href=&/?target=https%3A//babeljs.io/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&babel&i class=&icon-external&&&/i&&/a& 或者 &a href=&/?target=http%3A//www.typescriptlang.org/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&TypeScript&i class=&icon-external&&&/i&&/a&.。&br&CoffeeScript 注重改变 JavaScript 的语言风格 -- 可选的括号,显著的空格风格等等。 Babel 不是一门新语言而是一个编译器,把下一代的 JavaScript 中还未在所有浏览器实现的新特性(ES6 和之后)编译成更早更兼容的 JavaScript( ES5) 。TypeScript 是一门完全等同于下一代的 JavaScript 的语言,但加入了可选的静态类型。很多人选择 babel 因为更贴近普通的 JavaScript。&br&&br&来看一个例子,在我们刚才使用 webpack 构建的步骤中怎么使用 babel。首先使用命令行安装 babel(npm 包) 到项目中:&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&$ npm install babel-core babel-preset-env babel-loader --save-dev
&/code&&/pre&&/div&&p&注意到我们安装了三个独立的包作为开发依赖 -- &code&babel-core&/code&
是 babel 的主要部分,&code&babel-preset-env&/code& 是预定义编译哪些 JavaScript 的新特性,&code&babel-loader&/code& 是一个使 bebel 和 webpack 能够良好地协作的一个包。我们可以配置 webpack 来使用 &code&babel-loader&/code& :&/p&&div class=&highlight&&&pre&&code class=&language-js&&&span&&/span&&span class=&c1&&// webpack.config.js&/span&
&span class=&nx&&module&/span&&span class=&p&&.&/span&&span class=&nx&&exports&/span& &span class=&o&&=&/span& &span class=&p&&{&/span&
&span class=&nx&&entry&/span&&span class=&o&&:&/span& &span class=&s1&&'./index.js'&/span&&span class=&p&&,&/span&
&span class=&nx&&output&/span&&span class=&o&&:&/span& &span class=&p&&{&/span&
&span class=&nx&&filename&/span&&span class=&o&&:&/span& &span class=&s1&&'bundle.js'&/span&
&span class=&p&&},&/span&
&span class=&nx&&module&/span&&span class=&o&&:&/span& &span class=&p&&{&/span&
&span class=&nx&&rules&/span&&span class=&o&&:&/span& &span class=&p&&[&/span& &span class=&c1&&// 手动加粗&/span&
&span class=&p&&{&/span&
&span class=&nx&&test&/span&&span class=&o&&:&/span& &span class=&sr&&/\.js$/&/span&&span class=&p&&,&/span&
&span class=&nx&&exclude&/span&&span class=&o&&:&/span& &span class=&sr&&/node_modules/&/span&&span class=&p&&,&/span&
&span class=&nx&&use&/span&&span class=&o&&:&/span& &span class=&p&&{&/span&
&span class=&nx&&loader&/span&&span class=&o&&:&/span& &span class=&s1&&'babel-loader'&/span&&span class=&p&&,&/span&
&span class=&nx&&options&/span&&span class=&o&&:&/span& &span class=&p&&{&/span&
&span class=&nx&&presets&/span&&span class=&o&&:&/span& &span class=&p&&[&/span&&span class=&s1&&'env'&/span&&span class=&p&&]&/span&
&span class=&p&&}&/span&
&span class=&p&&}&/span&
&span class=&p&&}&/span&
&span class=&p&&]&/span&
&span class=&p&&}&/span&
&span class=&p&&};&/span&
&/code&&/pre&&/div&&p&语法可能看起来让人困惑(所幸并不需要经常编辑它)。基本上我们是在告诉 webpack 寻找任何 .js 结尾的文件(除了 &code&node_modules&/code& 目录)并使用 &code&babel-loader&/code& 加载、用 &code&babel-preset-env&/code& 作为设置编译 JavaScript 文件。你可以在&a href=&/?target=http%3A//webpack.github.io/docs/configuration.html& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&这里&i class=&icon-external&&&/i&&/a&看到更多关于 webpack 配置的信息。&br&&/p&&p&现在既然一切就绪,我们可以在 JavaScript 中写 ES2015 特性啦~这是在 &code&&b&index.js&/b&&/code& 中一个简单的关于 &a href=&/?target=https%3A//babeljs.io/learn-es2015/%23ecmascript-2015-features-template-strings& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&ES2015 模板字符串&i class=&icon-external&&&/i&&/a& 的例子:&/p&&div class=&highlight&&&pre&&code class=&language-js&&&span&&/span&&span class=&c1&&// index.js&/span&
&span class=&kd&&var&/span& &span class=&nx&&moment&/span& &span class=&o&&=&/span& &span class=&nx&&require&/span&&span class=&p&&(&/span&&span class=&s1&&'moment'&/span&&span class=&p&&);&/span&
&span class=&nx&&console&/span&&span class=&p&&.&/span&&span class=&nx&&log&/span&&span class=&p&&(&/span&&span class=&s2&&&Hello from JavaScript!&&/span&&span class=&p&&);&/span&
&span class=&nx&&console&/span&&span class=&p&&.&/span&&span class=&nx&&log&/span&&span class=&p&&(&/span&&span class=&nx&&moment&/span&&span class=&p&&().&/span&&span class=&nx&&startOf&/span&&span class=&p&&(&/span&&span class=&s1&&'day'&/span&&span class=&p&&).&/span&&span class=&nx&&fromNow&/span&&span class=&p&&());&/span&
&span class=&kd&&var&/span& &span class=&nx&&name&/span& &span class=&o&&=&/span& &span class=&s2&&&Bob&&/span&&span class=&p&&,&/span& &span class=&nx&&time&/span& &span class=&o&&=&/span& &span class=&s2&&&today&&/span&&span class=&p&&;&/span&
&span class=&nx&&console&/span&&span class=&p&&.&/span&&span class=&nx&&log&/span&&span class=&p&&(&/span&&span class=&sb&&`Hello &/span&&span class=&si&&${&/span&&span class=&nx&&name&/span&&span class=&si&&}&/span&&span class=&sb&&, how are you &/span&&span class=&si&&${&/span&&span class=&nx&&time&/span&&span class=&si&&}&/span&&span class=&sb&&?`&/span&&span class=&p&&);&/span&
&/code&&/pre&&/div&&p&我们也可以使用 &a href=&/?target=https%3A//babeljs.io/learn-es2015/%23ecmascript-2015-features-modules& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&ES2015 import 语句&i class=&icon-external&&&/i&&/a& 代替 &code&require&/code& 加载模块,就像现如今很多代码库中那样:&/p&&div class=&highlight&&&pre&&code class=&language-js&&&span&&/span&&span class=&c1&&// index.js&/span&
&span class=&kr&&import&/span& &span class=&nx&&moment&/span& &span class=&nx&&from&/span& &span class=&s1&&'moment'&/span&&span class=&p&&;&/span&
&span class=&nx&&console&/span&&span class=&p&&.&/span&&span class=&nx&&log&/span&&span class=&p&&(&/span&&span class=&s2&&&Hello from JavaScript!&&/span&&span class=&p&&);&/span&
&span class=&nx&&console&/span&&span class=&p&&.&/span&&span class=&nx&&log&/span&&span class=&p&&(&/span&&span class=&nx&&moment&/span&&span class=&p&&().&/span&&span class=&nx&&startOf&/span&&span class=&p&&(&/span&&span class=&s1&&'day'&/span&&span class=&p&&).&/span&&span class=&nx&&fromNow&/span&&span class=&p&&());&/span&
&span class=&kd&&var&/span& &span class=&nx&&name&/span& &span class=&o&&=&/span& &span class=&s2&&&Bob&&/span&&span class=&p&&,&/span& &span class=&nx&&time&/span& &span class=&o&&=&/span& &span class=&s2&&&today&&/span&&span class=&p&&;&/span&
&span class=&nx&&console&/span&&span class=&p&&.&/span&&span class=&nx&&log&/span&&span class=&p&&(&/span&&span class=&sb&&`Hello &/span&&span class=&si&&${&/span&&span class=&nx&&name&/span&&span class=&si&&}&/span&&span class=&sb&&, how are you &/span&&span class=&si&&${&/span&&span class=&nx&&time&/span&&span class=&si&&}&/span&&span class=&sb&&?`&/span&&span class=&p&&);&/span&
&/code&&/pre&&/div&&p&在这个例子中,&code&import&/code& 语法和 &code&require&/code& 并没有特别大的不同,但在更高级的案例中 &code&import&/code&
有更大的灵活性。由于修改了 &code&&b&index.js&/b&&/code& ,需要重新在命令行里运行 webpack:&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&$ ./node_modules/.bin/webpack
&/code&&/pre&&/div&&p&现在你可以在浏览器中刷新 &code&&b&index.html&/b&&/code&。在写作本文时,大多数的现代浏览器支持所有 ES2015 的特性,所以有时候很难辨别出 babel 有没有去做他该做的事儿。你可以在一些老式浏览器中测试一下比如 IE9 ,或者你可以看一下 &code&&b&bundle.js&/b&&/code& 找到编译后的代码: &/p&&div class=&highlight&&&pre&&code class=&language-js&&&span&&/span&&span class=&c1&&// bundle.js&/span&
&span class=&c1&&// ...&/span&
&span class=&nx&&console&/span&&span class=&p&&.&/span&&span class=&nx&&log&/span&&span class=&p&&(&/span&&span class=&s1&&'Hello '&/span& &span class=&o&&+&/span& &span class=&nx&&name&/span& &span class=&o&&+&/span& &span class=&s1&&', how are you '&/span& &span class=&o&&+&/span& &span class=&nx&&time&/span& &span class=&o&&+&/span& &span class=&s1&&'?'&/span&&span class=&p&&);&/span&
&span class=&c1&&// ...&/span&
&/code&&/pre&&/div&&p&在这儿你可以发现 babel 已经把 ES2015 的模板字符串编译成常规的 JavaScript 字符串连接来保持浏览器的兼容性。尽管这个特定的例子不是太令人兴奋,但能够编译代码是很强大的力量。JavaScript 迎来了一些令人兴奋的语言特性比如像
&a href=&/?target=https%3A//developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&async/await&i class=&icon-external&&&/i&&/a&,你可以从现在开始写出更好的代码。尽管编译有时候看起来比较繁琐、痛苦,但在过去的几年里它驱动语言有了很多激动人心的改进,因为人们能够在今天检验明天的特性。&br&&/p&&p&我们差不多要完成了,但在工作流中还是有些做的太粗糙的部分。如果我们关心性能的话,就应该&a href=&/?target=https%3A//en.wikipedia.org/wiki/Minification_%28programming%29& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&最小化&i class=&icon-external&&&/i&&/a&打包文件,这个过程应该足够简洁因为我们在构建过程已经合并了文件。还有在每次修改完 JavaScript 文件后我们仍然需要重新运行 webpack 命令。所以下一步我们将寻找一些方便的工具来解决这些难题。&/p&&h2&&b&使用自动构建工具(npm 脚本)&/b&&/h2&&p&现在既然使用构建过程来进行 JavaScript 模块化开发,那任务管理工具应该也会很有用,从而自动化不同的构建流程。对于前端开发来说,这些任务包括最小化代码文件、优化图片、运行测试等等。&/p&&p&2013 年,Grunt 是最流行的前端构建工具,Gulp 在不久后紧跟其后。它们都依赖一些集成了其他命令行工具的插件。最近最流行的选择似乎是使用 npm 内建的脚本功能自身,不使用插件而是直接使用其他的命令行工具。&/p&&p&来写一下能让 webpack 使用得更方便的 npm 脚本吧。只需要简单修改 &code&package.json&/code& 如下:&/p&&div class=&highlight&&&pre&&code class=&language-json&&&span&&/span&&span class=&p&&{&/span&
&span class=&nt&&&name&&/span&&span class=&p&&:&/span& &span class=&s2&&&modern-javascript-example&&/span&&span class=&p&&,&/span&
&span class=&nt&&&version&&/span&&span class=&p&&:&/span& &span class=&s2&&&1.0.0&&/span&&span class=&p&&,&/span&
&span class=&nt&&&description&&/span&&span class=&p&&:&/span& &span class=&s2&&&&&/span&&span class=&p&&,&/span&
&span class=&nt&&&main&&/span&&span class=&p&&:&/span& &span class=&s2&&&index.js&&/span&&span class=&p&&,&/span&
&span class=&nt&&&scripts&&/span&&span class=&p&&:&/span& &span class=&p&&{&/span& &span class=&err&&//&/span& &span class=&err&&手动加粗&/span&
&span class=&nt&&&test&&/span&&span class=&p&&:&/span& &span class=&s2&&&echo \&Error: no test specified\& && exit 1&&/span&&span class=&p&&,&/span&
&span class=&nt&&&build&&/span&&span class=&p&&:&/span& &span class=&s2&&&webpack --progress -p&&/span&&span class=&p&&,&/span&
&span class=&nt&&&watch&&/span&&span class=&p&&:&/span& &span class=&s2&&&webpack --progress --watch&&/span&
&span class=&p&&},&/span&
&span class=&nt&&&author&&/span&&span class=&p&&:&/span& &span class=&s2&&&&&/span&&span class=&p&&,&/span&
&span class=&nt&&&license&&/span&&span class=&p&&:&/span& &span class=&s2&&&ISC&&/span&&span class=&p&&,&/span&
&span class=&nt&&&dependencies&&/span&&span class=&p&&:&/span& &span class=&p&&{&/span&
&span class=&nt&&&moment&&/span&&span class=&p&&:&/span& &span class=&s2&&&^2.19.1&&/span&
&span class=&p&&},&/span&
&span class=&nt&&&devDependencies&&/span&&span class=&p&&:&/span& &span class=&p&&{&/span&
&span class=&nt&&&babel-core&&/span&&span class=&p&&:&/span& &span class=&s2&&&^6.26.0&&/span&&span class=&p&&,&/span&
&span class=&nt&&&babel-loader&&/span&&span class=&p&&:&/span& &span class=&s2&&&^7.1.2&&/span&&span class=&p&&,&/span&
&span class=&nt&&&babel-preset-env&&/span&&span class=&p&&:&/span& &span class=&s2&&&^1.6.1&&/span&&span class=&p&&,&/span&
&span class=&nt&&&webpack&&/span&&span class=&p&&:&/span& &span class=&s2&&&^3.7.1&&/span&
&span class=&p&&}&/span&
&span class=&p&&}&/span&
&/code&&/pre&&/div&&p&在这里我们添加了两个新脚本,&code&build&/code& 和 &code&watch&/code& 。运行构建任务,就在命令行里敲:&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&$ npm run build
&/code&&/pre&&/div&&p&这会运行起 webpack (使用我们之前写的 &code&&b&webpack.config.js&/b&&/code& 中的配置 )并带有 &code&--progress&/code& 选项显示进程, &code&-p&/code& 选项则会最小化生产代码。执行 &code&watch&/code& 脚本:&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&$ npm run watch
&/code&&/pre&&/div&&p&使用 &code&--watch&/code& 选项从而在每次修改完 JavaScript 文件后能够自动重新运行 webpack 命令,这对开发人员来说十分方便。&/p&&p&注意到在 &code&&b&package.json&/b&&/code& 中的脚本无需指明 webpack 的完整路径 &b&&code&./node_modules/.bin/webpack&/code&,&/b&,因为 node.js 知道每一个 npm 包的位置。很贴心吧~ 我们甚至可以安装 webpack-dev-server -- 一个简单的带有热更新的 web 服务器来让开发变得更美好。安装它作为开发依赖的话,只需要:&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&$ npm install we
bpack-dev-server --save-dev
&/code&&/pre&&/div&&p&然后再向 &code&&b&package.json&/b&&/code& 中添加一行脚本:&/p&&div class=&highlight&&&pre&&code class=&language-json&&&span&&/span&&span class=&p&&{&/span&
&span class=&nt&&&name&&/span&&span class=&p&&:&/span& &span class=&s2&&&modern-javascript-example&&/span&&span class=&p&&,&/span&
&span class=&nt&&&version&&/span&&span class=&p&&:&/span& &span class=&s2&&&1.0.0&&/span&&span class=&p&&,&/span&
&span class=&nt&&&description&&/span&&span class=&p&&:&/span& &span class=&s2&&&&&/span&&span class=&p&&,&/span&
&span class=&nt&&&main&&/span&&span class=&p&&:&/span& &span class=&s2&&&index.js&&/span&&span class=&p&&,&/span&
&span class=&nt&&&scripts&&/span&&span class=&p&&:&/span& &span class=&p&&{&/span&
&span class=&nt&&&test&&/span&&span class=&p&&:&/span& &span class=&s2&&&echo \&Error: no test specified\& && exit 1&&/span&&span class=&p&&,&/span&
&span class=&nt&&&build&&/span&&span class=&p&&:&/span& &span class=&s2&&&webpack --progress -p&&/span&&span class=&p&&,&/span&
&span class=&nt&&&watch&&/span&&span class=&p&&:&/span& &span class=&s2&&&webpack --progress --watch&&/span&&span class=&p&&,&/span&
&span class=&nt&&&server&&/span&&span class=&p&&:&/span& &span class=&s2&&&webpack-dev-server --open&&/span& &span class=&err&&//&/span& &span class=&err&&手动加粗本行&/span&
&span class=&p&&},&/span&
&span class=&nt&&&author&&/span&&span class=&p&&:&/span& &span class=&s2&&&&&/span&&span class=&p&&,&/span&
&span class=&nt&&&license&&/span&&span class=&p&&:&/span& &span class=&s2&&&ISC&&/span&&span class=&p&&,&/span&
&span class=&nt&&&dependencies&&/span&&span class=&p&&:&/span& &span class=&p&&{&/span&
&span class=&nt&&&moment&&/span&&span class=&p&&:&/span& &span class=&s2&&&^2.19.1&&/span&
&span class=&p&&},&/span&
&span class=&nt&&&devDependencies&&/span&&span class=&p&&:&/span& &span class=&p&&{&/span&
&span class=&nt&&&babel-core&&/span&&span class=&p&&:&/span& &span class=&s2&&&^6.26.0&&/span&&span class=&p&&,&/span&
&span class=&nt&&&babel-loader&&/span&&span class=&p&&:&/span& &span class=&s2&&&^7.1.2&&/span&&span class=&p&&,&/span&
&span class=&nt&&&babel-preset-env&&/span&&span class=&p&&:&/span& &span class=&s2&&&^1.6.1&&/span&&span class=&p&&,&/span&
&span class=&nt&&&webpack&&/span&&span class=&p&&:&/span& &span class=&s2&&&^3.7.1&&/span&
&span class=&p&&}&/span&
&span class=&p&&}&/span&
&/code&&/pre&&/div&&p&现在你可以在命令行运行 dev server:&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&$ npm run server
&/code&&/pre&&/div&&p&这会在你浏览器 &code&localhost:8080&/code&(默认)地址打开你的 &code&&b&index.html&/b&&/code& 网页。只要你修改了 &code&&b&index.js&/b&&/code& 中的代码,webpack-dev-server 就会重新打包 JavaScript 并自动刷新浏览器。这真的相当节省时间,能够使你注意力集中在代码本身而不是一直在浏览器和代码之间来回切换观察变化。&/p&&p&&br&&/p&&p&上面这些仅仅只是触及到了表面,不论是 webpack 还是 webpack-dev-server(你可以从&a href=&/?target=https%3A//webpack.js.org/guides/development/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&这里&i class=&icon-external&&&/i&&/a&阅读更多)都有相当多的选项。你当然也可以写 npm 脚本运行其他任务,比如把 Sass 转换为 CSS,压缩图片,运行测试等等。npm 脚本本身也有很多高级选项 和技巧 -- &a href=&/?target=https%3A///k88hudson& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Kate Hudson&i class=&icon-external&&&/i&&/a& 的这个 &a href=&/?target=https%3A///watch%3Fv%3D0RYETb9YVrk%26t%3D12s%26list%3DWL%26index%3D11& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&talk&i class=&icon-external&&&/i&&/a& 就是一个很棒的开始。&/p&&p&&br&&/p&&h2&&b&结语&/b&&/h2&&p&这就是简明的现代 JavaScript。我们从最简单的 HTML 和 JS 到使用包管理工具自动下载第三方包,使用模块打包器生成单个文件,利用编译工具使用未来的 JavaScript 特性,使用任务构建工具来自动化代码构建过程的不同部分。毫无疑问变化了很多,尤其对于初学者来说。Web 开发过去对于新学编程的人来说是一个很好的入门点,因为很容易就能开始,运行。而现在日新月异不断变化的工具让人畏惧。&/p&&p&仍然没有看起来那么糟。一切正在逐渐稳定下来,尤其是前端适应 node 生态系统已经成为一种可行的方式。使用 npm 作为包管理工具使得前后端更加统一,node &code&require&/code& 或者 &code&import&/code& 语句可以进行模块化开发,npm 脚本自动运行任务。比起一两年前这大大简化了工作流!&/p&&p&对于初学者或者有经验的开发者更棒的是现如今的许多框架都带有工具让初始化项目更方便。Ember 有 &code&&u&&a href=&/?target=https%3A///& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&ember-cli&i class=&icon-external&&&/i&&/a&&/u&&/code&
,对 Angular 的 &code&&u&&a href=&/?target=https%3A//cli.angular.io/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&angular-cli &i class=&icon-external&&&/i&&/a&&/u&&/code& 的很大影响。还有 React 的 &code&&u&&a href=&/?target=https%3A///facebookincubator/create-react-app& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&create-react-app&i class=&icon-external&&&/i&&/a&&/u&&/code& , Vue 的 &code&&u&&a href=&/?target=https%3A///vuejs/vue-cli& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&vue-cli&i class=&icon-external&&&/i&&/a&&/u&&/code&
等等。这些工具都会把你几乎需要的一切准备好 -- 你需要做的就是开始写代码。然而这些工具并不是魔法,它们仅仅是把一切统一并跟上工作潮流 -- 你也可能经常需要对你的 webpack, babel 等等做一些额外的配置。所以理解每一块都做了什么仍然至关重要,就像我们在本篇文章涉及的那样。&/p&&p&现代 JavaScript 有时可能真的会让人觉得很沮丧,因为飞速的变化和发展。尽管有时候看起来像是在重复造轮子,JavaScript 的快速进化却推动着创新,比如热更新,实时 linting,时光旅行般的调试。作为一个开发者这简直让人兴奋。希望这些信息,在你的旅途中能够有意义~&/p&&figure&&img src=&/v2-bd0c06dede79a5f587b75_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&543& data-rawheight=&548& class=&origin_image zh-lightbox-thumb& width=&543& data-original=&/v2-bd0c06dede79a5f587b75_r.jpg&&&/figure&&p&Special thanks to &i&&a href=&/?target=https%3A///ryanqnorth& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&@ryanqnorth&i class=&icon-external&&&/i&&/a&’s &a href=&/?target=http%3A///& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Dinosaur Comics&i class=&icon-external&&&/i&&/a& 。&/i&&/p&
原文链接: 作者:
译者: 转载请注明出处有时候入门没入好,学习起现代的 JavaScript 开发还是颇有难度的。生态系统太日新月异以至于让人难以理解不同工具的出现究竟是为了解决什么问题。我从 1…
&figure&&img src=&/v2-c2ff90f5e28e2fb39ccc1_b.jpg& data-rawwidth=&600& data-rawheight=&367& class=&origin_image zh-lightbox-thumb& width=&600& data-original=&/v2-c2ff90f5e28e2fb39ccc1_r.jpg&&&/figure&&blockquote&前几日听到一句生猛与激励并存,可怕与尴尬同在,最无奈也无解的话:“90后,你的中年危机已经杀到”。这令我很受触动。显然,这有些夸张了,但就目前这日复一日的庸碌下去,眨眼的功夫,那情形就会在这骨感的现实面前,悄然的被显现。所以,越发体验到,当必要有计划的去做,去写,去玩,去嗨,利用好这荷尔蒙分泌还算旺盛的时光,去厚积去博取,去发现去折腾;让自己的生命不在仅是工作与惆怅,还有时间分与“诗和远方”。不用分析,就知道这该如何去做,高效去完成工作,然后去学着优雅地生而活。目前犹身为前端开发者,且在使用 Vue,那么就有了此文;这不仅是纪录或分享,也是在漫漫之路上下求索,更希望能探讨和指点,以资见识,提升其效。&/blockquote&&figure&&img src=&/v2-8a268a8ecdea_b.jpg& data-caption=&& data-rawwidth=&940& data-rawheight=&400& class=&origin_image zh-lightbox-thumb& width=&940& data-original=&/v2-8a268a8ecdea_r.jpg&&&/figure&&p&&b&微注:&/b& 早先在写[如何优雅地使用Sublime Text]时候,前后历经10月,至今虽不断更新犹在,离该话题也是相去甚远。所以,谈及此一个宽广话题的存在,欲一谈也须深入研究,非朝夕可至;所以本篇将采取不定期更新,当然,这么做,也是治疗自身拖延症之一法子;另外也是限制聚合网抓取的一种尝试。&br&&b&更新:&/b& 对于如何构建 VueJs 项目,自然推荐官方的脚手架 vue-cli&br&;而对于微小型项目,个人倒挺看好poi —— (Delightful web development),它能让你十分便捷的使用当前流行的框架(Vue React等)。即便如此呢,很多业界朋友,对 Vue 项目的构建,还是不尽如人意;鉴于此,有根据过往的些许经验,设计出一套样板 ——vue-boilerplate-template,以供参考,当然也期待朋友给予指正。其中已经依赖了&code&vue-router&/code&&br&、&code&vuex&/code&、 &code&vue-i18n&/code&、 element-ui、 bootstrap 诸多库;也注入了 &code&webpack&/code&、 &code&Eslint&/code&、 &code&pre-commit&/code&等等便捷开发相关的库。其中对与后台接口调用与使用,vuex 的运用,视图结构的塑造,路由和多语言的配置,公共方法的调度,webpack打包优化等等,都基于便捷开发的前提下,做了相应的设计,希望有缘人会喜欢;这一番设计缘由,得空会另起一篇文章予以阐明;而这番设计也会,在不断的学习中持续改进,敬请期待&/p&&p&&b&随言&/b&: 身在程序的江湖,如你是一位即将出征武士,对决于浩瀚无尽的需求大军;那么你不仅需要一副好的体格,还需要一身技艺:而这软件工程学&br&(抑或加算法)就好比内功(查克拉);而所使用的各家语言&br&,则好如武学招式(独孤九剑?);那加以利用的各种工具,当如随身利器(小李飞刀?);那属于自己一套极致开发流程,便是轻功(电光神行步?)……如是斯言,那么作为开发者的你,几技傍身耶?&br&如上随言,此篇准备从以下几个方面来探讨:&/p&&p&&b&如何漂亮使用 Vue 之工具篇&/b&&/p&&p&欲先利其器,必先利其器,这是此博客一大倡导;关于如何优雅地去写好 Vue,工具自是首当其冲要提及的,毕竟这非常重要;在你选择使用 Vue 来从事前端开发的那一刻,你已经同意的这一论点:毕竟 Vue 也是用原生 Js 写的,Js 则是用 C 语言写,而 C 又是汇编写的….. 这不再是刀耕火种的年代,而你也未用汇编或 C 来解决你的需求,So,你是同意的。既是赞同的,岂有不用好它的道理?那么来一起探讨下:&/p&&p&&b&外设&/b&:除了那些舒适坐骑与书桌外,双屏显示器,&code&Mac&/code&则是必备外设装备;你知道,一屏编辑器中写着代码的同时,就能在另一屏 Chrome 下看到表现,这很高效便捷,也令人很是舒服。而 Mac 这&b&设备中堪称优雅情人&/b&的存在,更是居家良品。倘若,所处的工作环境没那么看重效率,或者未表现出该有的慷慨,则一定须善待自己的精力和时间,勇于将自己的开发环境打造精良。&/p&&p&&b&软件&/b&:身为开发人员,你电脑以及其中配备的软件,就好如武士手中的利剑,是助你大杀四方的存在;所以无论是用它来玩一玩恶作剧,还是来致敬把Dota,抑或是搞搞需求,皆十分有必要将其锋利化。因此,诸如 Alfred,Brew,Iterm2,Oh-my-zh,Git等必备就不说了;对于前端开发,编辑器与浏览器的配备与运用,尤其重要(对于这一点很多前端开发者,尚未达到及格,一如其水平);对于浏览器,只推荐&code&Chrome&/code&,不只是浏览或者调试,更在于其搜索。而编辑器则推荐 &code&SublimeText3&/code&与 &code&Atom&/code&;&code&VsCode&/code&也很棒的存在,写前端后台都十分趁手(目测 Google 也都力推之);不太推荐使用 &code&WebStorm&/code&,因为其除了反人类的操作设计外,感受不到其他可记住点。&/p&&p&&b&周边&/b&:使用 Vue 开发开发前端,当须保持对周边工具体系,经常保持关注,比如&code&Node&/code&,&code&Npm(Yarn)&/code&,&code&Webpack&/code&,&code&Gulp&/code&等,以及&code&Lodash&/code&,&code&superagent&/code&,&code&d3&/code&等工具库,再有就是 Vue 系本身具库,譬如&code&Vue-cli&/code&, &code&vue-router&/code&等辅助;再有就是不断衍生出来的 Vue 插件扩展。&b&Atwood定律中阐述到&/b&:&b&Any application that can be written in JavaScript, will eventually be written in JavaScript.&/b&(翻译过来即是:凡是能用JavaScript写出来的,最终都会用JavaScript写出来)。这个理论同样适用于 Vue,它简易强大的存在,吸引了很多超厉害的开发者或团队,为其贡献了无数好用的组件库。比如: 饿了么出品的Element-UI,还有 vue-echarts,vue-multiselect…… 具体可以参看awesome-vue,略睹其繁华似锦。&/p&&figure&&img src=&/v2-4fab3ebd6efc9_b.jpg& data-caption=&& data-rawwidth=&900& data-rawheight=&550& class=&origin_image zh-lightbox-thumb& width=&900& data-original=&/v2-4fab3ebd6efc9_r.jpg&&&/figure&&h2&如何漂亮使用-Vue-之基础篇)&b&如何漂亮使用 Vue 之基础篇&/b&&/h2&&hr&&p&&b&软件工程学&/b&,作为程序员,本就该是当学好的一门技艺。像&b&[代码大全2]&/b&以及&b&[程序整洁之道]&/b&,一定是需要好好读一读的。Web 前端开发,因其入门的容易性(还有需求的旺盛),造就了这一行涌进了不少急功近利者,也惊现了很多令人“不堪卒读”的代码。而前端发展日新月异,如不能渐而掌握,长期来看,委屈的倒也不全是别人(读你代码者),更是自己;举个浅显的例子来讲,如不能学会很好的组织代码结构,即便有高手写了架构,一旦项目渐大,不也是照样面临被自己坑苦的凄楚?事实上,不乏很多开发者,未能养成很好的编码素养,基础如变量方法命名,也是能令人心惊肝颤;很显然这是损人不利己的行为,势必当善之。&/p&&p&对于团队来讲,&code&Eslint&/code&实在是需要配备的利器;既然难以保证每个人都很有素养,那么必须适当强制;至少避免了丛生些杂乱不堪的代码,以乱军心。当然,使用伊始,总会有些人不太适应,所以玩转编辑器的重要性,就再次体现出其价值了;由此也引出了自动化(半)工作流的话题了,这在之后的内容中会加以探讨。&/p&&p&&b&前端基础技术&/b&,从事前端开发,长久之计来看,基本功是非常重要的;尤其是 JavaScript;这在写 Vue 时候,也体现的比较明显。其他如 Html,Css,自然不用说;除此之外,Scss 等预处理器,也是当学习并加以运用,以提升开发效率,节省开发成本;毕竟只有节省出充裕的时间来,才会去做更多优化,节约出更多精力与时间,一个优良的循环就此得以形成。&/p&&p&&b&Vue 基础&/b&,这一点很重要,熟读[Vue.js 官方教程],再没有比这更好的教程了;根据之前经验来看,心急是吃不到热豆腐的,欠下的也终究得还;至少起初需通读之,否则遇到问题,无法及时定位出在哪儿查究,这无疑会浪费更多时间。除此之外,Github 上找一份好的微型项目,认真读下,可以发掘出很多值得学习的玩法。&/p&&p&&b&善用配置&/b&,《代码大全》第 18 章,讲到&b&表驱动法&/b&(Table-Driven Methods),对于编程从业者,很有必要一读。很多时候,可借助查询表来加以简化逻辑和继承树关系。这在团队协作,分模块开发模式具有更非凡价值;应该善用配置,将各个模块予以抽离,使得相互间不存强依赖,如此开发环节也大大的避免代码冲突。譬如,了解 JavaScript 特性,即可做如下写法:&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&const files = require.context('.', true, /\.svg$/)
const modules = {}
files.keys().forEach((key) =& {
if (key === './index.js') return
modules[key.replace(/(\.\/|\.svg)/g, '')] = files(key)
export default modules
&/code&&/pre&&/div&&p&这样即可写出便捷的 [Icon Component],使用时只需添加新 Svg 入 assets,然后引用 icon 时填写对应 Svg 名字即可,十分方便;推此及它,我们可借助这样配置,去分解、组合各个模块,甚是方便。&/p&&hr&&blockquote&Vue有三大特性,十分令人欣喜;一是其数据的双向绑定,即:通过数据绑定链接View和Model,让数据的变化自动映射为视图的更新。另一个是其数据驱动的组件系统,即:用嵌套的组件树来描述用户界面(而一个组件恰恰可以对应MVVM中的ViewModel),其三是基于构建工具的单文件组件格式,即其所提供了强大的loader API,来定义对不同文件格式的预处理逻辑,从而让我们可以将CSS、模板,甚至是自定义的文件格式等,当做JavaScript模块来使用,极大提升了代码的可复用性;Webpack 基于loader还可以实现大量高级功能,比如自动分块打包并按需加载、对图片资源引用的自动定位、根据图片大小决定是否用base64内联、开发时的模块热替换等等。当然 Vue 还具有其他若干令人击节赞叹的设计。&/blockquote&&p&鉴于此,如果可以很熟练的掌握其数据的绑定与传输,组件的开发,以及周边 Webpack 等相关配置,则能将运用水平视为进入了一个新的层次。据以往经验来看,这不是一件容易的事儿,毕竟使用这 Vue 也是冲着解决需求去了,而非在搞研究。谁能说开车上路的司机,能了解关乎车的所有?相信,接下来的很长时间里,都须对这几方面加以学习、探索,然后加以利用。&/p&&p&如何漂亮使用-Vue-之实战组件篇)&b&如何漂亮使用 Vue 之实战组件篇&/b&&/p&&hr&&p&Vue 一大特色是用嵌套的组件树来描述用户界面。所以组件的设计与编写至关重要;至少要保证她是易于修改和维护,可复用性和可读性高,耦合度低,接纳团队合作性开发… … 诸此等等。项目一旦庞杂,更得事先考虑好整个架构的设计,使其清晰合理;组件缓存的使用、避免过重组件的衍生 … 。而 Vue 组件系统又是有数据所驱动,更得兼顾数据在各种组件间通信,避免数据被多方操作,Bug 难以定位等问题。&/p&&p&这是一个须长期积淀的技能,非朝夕可至。但,部分内容只需刻意关注,即可见其成效的。比如,简明且见名知义的命名,良好的编码规范,团队统一编码风格,以保证代码的可读性。运用设计模式原则,比如&b&单一职责原则&/b&,将组件拆分抽离成更细粒度,保证组件功能单一,以提升组件复用行;再如&b&接口隔离原则&/b&,采用稳定的服务端接口,将变化模块分离,使得组件得以解耦;在复杂的项目中,也是需要用到冗余、继承,这时候也需要关注下&b&里氏替换原则&/b&、&b&依赖倒置原则&/b&… 。另外还当学习 Vue 本身所提供的优化,像[路由懒加载], 即:结合 Vue 的 异步组件 和 Webpack 的 code splitting feature, 轻松实现路由组件的懒加载,使得该组件访问时才加载,以提升页面加载效率,还有利用服务端实现首屏渲染,组件缓存等等,尤须注意的是组件间数据通信,这在之后一节中会提及,此处不做赘述。&/p&&p&这里需要学习探究的点很多,非片言可蔽之,看到一份 PPTVue.js实践: 如何使用Vue2.0开发富交互式WEB应用;个种谈到 Vue 许多相关的点,值得一览。另外,如是为团队写公用组件,一定记得附上对应使用文档,这很重要。你看,如上所说,要写好一手漂亮 Vue(代码),软件设计学问,是少不了的存在,不是么?&/p&&p&如何漂亮使用-Vue-之实战通信篇)&b&如何漂亮使用 Vue 之实战通信篇&/b&&/p&&hr&&p&早先有在[Vue 各类数据绑定]一文中,对 Vue 数据绑定有过些描述(version 1.&i&);虽然如今 Vue 早已升级至 2.&/i&,不过数据绑定变化虽多,但大局影响不大,譬如:不再允许片段实例;须以v-html取代三 Mustache 语法;变更 v-for 遍历时参数顺序等等,具体可参见[从 Vue 1.x 迁移]。此处就数据在 vue 组件间传递做下探讨。&/p&&p&Vue2 移除 $dispatch() 和 $broadcast()之后,主要通过 prop&br&(包括 v-model 自定义) 实现父组件向子组件传参,且只能单向传递;&b&为了防止对父组件产生反向影响,Vue2 已移除了 .once 和 .sync 修饰符,子组件需要显式地传递一个事件而不是依赖于隐式地双向绑定。&/b& 一旦你试图在组件内,直接修改通过props传入的父组件数据,这将被认为是anti-pattern的,报以下错误:&/p&&blockquote&Avoid mutating a prop directly since the value will be overwritten whenever the parent component re-renders. Instead, use a data or computed property based on the prop’s value.&/blockquote&&p&但,如果传递的 prop 本身是引用型传递,像对象或者数组,由于数据类型自身特性,无论是什么绑定方式都会是双向绑定!这些Vue文档-单向数据流中有作说明;请看这个例子:&/p&&p&这里需要留意的是:Vue 要么监听的是基本数据类型的值变化,要么监听的是引用数据类型的&b&引用变化&/b&;因此,vue对于数组,才自己封装了一套方法(包括&code&$set&/code& , &code&$remove&/code&),如果直接变更引用类型的内容,即便数据已经修改,但 Vue 是感知不到的,所以视图将不会更新(针对性的对属性进行赋值操作,则会调用其属性的 set 方法,因此Vue会得到感知,从而驱动视图更新)。这里需要补充的是:Vue 使用 Object.defineProperty(ES5特性)将数据转为 &code&getter/setter&/code&,从而实现对数据的 &code&watcher&/code&,&code&setter&/code&被调用时重新绘制关联的 Dom,从而刷新视图。&/p&&p&所以,对父组件传递来引用型数据,如需更改,最好改动做深度拷贝后的数据,而且需要注意得失,&code&Object.assign&/code&不是深度拷贝,即便采用了 &code&Object.freeze()&/code&去冻结。对于子组件向父组件回传参数,可借助 &code&$emit&/code&,当然也可以使用 callback Functon,可参见jsfidle示例。非父子组件间通信,Vue 有提供 &code&Vuex&/code&,以状态共享方式来实现同信,对于这一点,应该注意考虑平衡,从整体设计角度去考量,确保引入她的必要。如果项目不怎么复杂的话,完全可以自己设计一套 &code&vue-bus&/code&,以提供了一个全局事件中心,使得可以像使用内置事件流一样,便捷的使用全局事件。当然,Vue 也提供了 &code&$refs&/code&,可以跨层调用,或者诸如这样&code&this.$parent.$parent&/code&;提供了不代表推荐;尽量少的去运用,除非逼不得已,或者去恶作剧坑人。当然,也可借助原生Api &i&sessionStorage&/i&, &i&localStorage&/i&等等进行数据存储,以到达通信目的;对于,兼顾得失,争取扁平统一化通信方式就好。鉴于篇幅,就不多赘述。&/p&&h2&如何漂亮使用-Vue-之Webpack篇)&b&如何漂亮使用 Vue 之Webpack篇&/b&&/h2&&hr&&p&前文提到,推荐使用Vue-cli,它已然帮助我们贴心的配置好了 Webpack 相关。在编写 router 配置之时,可以轻松实现路由组件的懒加载,使得项目可以拆分成若干个 js 小包,和一个略大的 vendor,运行时按需去加载。即,我们可以像如下用法,去配备路由组件(当然,我们也可以把组件按组分块):&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&import Frame from './../views/Frame'
export default {
path: '/',
component: Frame,
children: [{
path: '/nicelinks',
title: setTitleLang('晚晴幽草轩', 'Nice Home Blog')
component: resolve =& require(['./../views/Nicelinks'], resolve)
&/code&&/pre&&/div&&p&&b&DllReferencePlugin&/b&&br&除此之外,在&code&webpack这块&/code&,还是有非常多东西需要去优化,以缩短包构建的时间、改善其体积等等。比如可利&code&DllReferenc

我要回帖

更多关于 arch 安装脚本 的文章

 

随机推荐