天給大家推薦這個HTML5開發手冊,希望能幫助正在學習web前端的人,鄙人也是剛學習前端沒多久,借助于一點資訊平臺能夠結識更多前端大牛,這是我的HTML5進階學習一點資訊群:250777811,里面有很多大牛隨時解答學習問題,每天晚上休息的時候還有免費的企業項目解決,歡迎初學者和進階的伙計申請加入。
1、HTML5中文手冊
通過制定如何處理所以HTMl元素以及如何從錯誤中恢復的緊缺規則,HTML5改進了互操作性,并2減少了開發成本。HTML5中的新特性包括了嵌入音頻、視頻和圖形的功能,客戶端數據存儲,以及交互式文檔。
2、 CSS完全參考手冊3.0下載
3、JavaScript參考手冊
JavaScript 本地對象和內置對象 Browser 對象(BOM)、 HTML DOM 對象 、JavaScript 對象參考手冊 本參考手冊描述每個對象的屬性和方法,并提供實例。
4、jQuery 1.4參考手冊
2010年1月22日,更新至JQuery 1.4版本,本版是參考shawphy的1.4在線版本制作,更新了好多以前的內容,以前沒仔細核對過,發現之前網上流行的chm版本基本都基于1.2的,1.3的內容很多都沒加進去,這次都補全了。用*標注了1.3版本新加的內容,@標注1.4新加的內容,方便大家查看。
5、Ajax中文手冊
AJAX是一種運用JavaScript和可擴展標記語言(XML),在網絡瀏覽器和服務器之間傳送或接受數據 的技術。AJAX可以用來和數據端進行數據的交互聯通。AJAX可以用來創建更多交互式的網絡應用程序。
6、Bootstrap3參考手冊
Bootstrap 是基于 HTML、CSS、JAVASCRIPT 的,它簡潔靈活,使得 Web 開發更加快捷。它由Twitter的設計師Mark Otto和Jacob Thornton合作開發,是一個CSS/HTML框架。Bootstrap提供了優雅的HTML和CSS規范,它即是由動態CSS語言Less寫成。
全部HTML5手冊內容都已經上傳群文件了250777811
關注悟空頭條,每日收獲HTML5學習干貨,傳播正能量,吾有本頭條!
<dependency>
<groupId>net.mingsoft</groupId>
<artifactId>模塊</artifactId>
<version>版本號</version>
<classifier>sources</classifier>
<scope>provided</scope>
</dependency>
基于MIT開源協議,可直接商用無需授權,但請尊重開源精神不要去掉代碼中銘飛的注釋和版權信息
建議開發者使用以下環境,這樣避免版本帶來的問題
MCms內容插件提供最基本的菜單、權限、角色、欄目、內容、靜態化、等常用功能。
視頻教程:內容插件視頻教程 配合代碼生成器使用快速提升開發效率:代碼生成器在線視頻教程、代碼生成器使用文檔
<!-- ms-mcms 內容模塊插件 -->
<dependency>
<groupId>net.mingsoft</groupId>
<artifactId>ms-mcms</artifactId>
<version>當前版本</version>
</dependency>
<!-- ms-mcms 內容模塊源碼 -->
<dependency>
<groupId>net.mingsoft</groupId>
<artifactId>ms-mcms</artifactId>
<version>當前版本</version>
<classifier>sources</classifier>
</dependency>Copy
項目訪問路徑/swagger-ui.html#/
系統部署手冊
懶人做法,將所有的資源打成一個jar包,維護資源不方便,不推薦
mvn clean package
java -jar ms-mcms.jarCopy
打包指令增加參數 -f bin-xml ,執行完成會在target目錄會生成 “ 項目-bin ” 發布文件夾
mvn clean package -f bin-xml
Copy
config:配置文件
html:靜態化自動生成的目錄(自動生成)
static:靜態資源文件
templets:(必須)模版目錄,需要復制一份
upload:(必須)上傳的文件夾
WEB-INF:ftl視圖文件
mcms.log:自動生成的日志文件
*.sh:linux啟動、停止腳本
*.bat:window啟動、停止腳本
技術 | 名稱 | 官網 |
Spring Framework | 容器 | http://projects.spring.io/spring-framework |
Spring Boot | MVC框架 | https://spring.io/projects/spring-boot |
Apache Shiro | 安全框架 | http://shiro.apache.org |
Spring session | 分布式Session管理 | http://projects.spring.io/spring-session |
MyBatis | ORM框架 | http://www.mybatis.org |
Freemarker | 視圖框架 | http://freemarker.foofun.cn |
PageHelper | MyBatis分頁插件 | http://git.oschina.net/free/Mybatis_PageHelper |
Log4J | 日志組件 | http://logging.apache.org |
Maven | 項目構建 | http://maven.apache.org |
Elasticsearch | 分布式搜索引擎 | https://www.elastic.co |
Redis | 分布式緩存數據庫 | https://redis.io |
hutool | 工具類 | http://hutool.mydoc.io |
技術 | 名稱 | 官網 |
vue | 函式庫 | https://cn.vuejs.org// |
element ui | UI庫 | https://element.eleme.cn/2.0/#/zh-CN |
jQuery | 函式庫 | http://jquery.com/ |
Bootstrap | 前端框架 | http://getbootstrap.com/ |
Bootstrap-table | Bootstrap數據表格 | http://bootstrap-table.wenzhixin.net.cn/ |
BootstrapValidator | 表單驗證 | http://bootstrapvalidator.com/ |
Font-awesome | 字體圖標 | http://fontawesome.io/ |
Waves | 點擊效果插件 | https://github.com/fians/Waves/ |
zTree | 樹插件 | http://www.treejs.cn/v3/ |
Select2 | 選擇框插件 | https://github.com/select2/select2 |
Vue | MVVM框架 | https://cn.vuejs.org/ |
AmazeUI | 移動端UI | http://amazeui.org/ |
Plupload | 上傳控件 | http://www.plupload.com/ |
freemarker | 模板引擎 | http://freemarker.foofun.cn/toc.html |
validator | 驗證庫 | https://github.com/chriso/validator.js |
animate | 動畫 | http://daneden.github.io/animate.css/ |
icon | 矢量小圖標(待更新) | http://ms.mingsoft.net/html/86//6048/index.html |
做開源我們是業余的,寫代碼我們是認真的。研發產品的路上我們一直在探索、一直在學習、一直在用心投入,希望能給更多的企業與開發者提供一些更有價值的服務。
源碼資料獲取方式:關注小編+轉發文章+私信【 666 】免費獲取
八股文面試資料獲取方式:關注小編+轉發文章+私信【 13 】免費獲取
重要的事情說三遍,轉發+轉發+轉發,一定要記得點贊轉發哦!!!
面試官:Spring 和 Spring Boot 的區別是什么?
對于 Spring和 SpringBoot到底有什么區別,我聽到了很多答案,剛開始邁入學習 SpringBoot的我當時也是一頭霧水,隨著經驗的積累、我慢慢理解了這兩個框架到底有什么區別,相信對于用了 SpringBoot很久的同學來說,還不是很理解 SpringBoot到底和 Spring有什么區別,看完文章中的比較,或許你有了不同的答案和看法!
作為 Java開發人員,大家都 Spring都不陌生,簡而言之, Spring框架為開發 Java應用程序提供了全面的基礎架構支持。它包含一些很好的功能,如依賴注入和開箱即用的模塊,如:
SpringJDBC、SpringMVC、SpringSecurity、SpringAOP、SpringORM、SpringTest,這些模塊縮短應用程序的開發時間,提高了應用開發的效率例如,在 JavaWeb開發的早期階段,我們需要編寫大量的代碼來將記錄插入到數據庫中。但是通過使用 SpringJDBC模塊的 JDBCTemplate,我們可以將操作簡化為幾行代碼。
SpringBoot基本上是 Spring框架的擴展,它消除了設置 Spring應用程序所需的 XML配置,為更快,更高效的開發生態系統鋪平了道路。
SpringBoot中的一些特征:
1、創建獨立的 Spring應用。
2、嵌入式 Tomcat、 Jetty、 Undertow容器(無需部署war文件)。
3、提供的 starters 簡化構建配置
4、盡可能自動配置 spring應用。
5、提供生產指標,例如指標、健壯檢查和外部化配置
6、完全沒有代碼生成和 XML配置要求
首先,讓我們看一下使用Spring創建Web應用程序所需的最小依賴項
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>5.1.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.1.0.RELEASE</version>
</dependency>
與Spring不同,Spring Boot只需要一個依賴項來啟動和運行Web應用程序:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.0.6.RELEASE</version>
</dependency>
在進行構建期間,所有其他依賴項將自動添加到項目中。
另一個很好的例子就是測試庫。我們通常使用 SpringTest, JUnit, Hamcrest和 Mockito庫。在 Spring項目中,我們應該將所有這些庫添加為依賴項。但是在 SpringBoot中,我們只需要添加 spring-boot-starter-test依賴項來自動包含這些庫。
Spring Boot為不同的Spring模塊提供了許多依賴項。一些最常用的是:
spring-boot-starter-data-jpaspring-boot-starter-securityspring-boot-starter-testspring-boot-starter-webspring-boot-starter-thymeleaf
有關 starter的完整列表,請查看Spring文檔。
讓我們來看一下 Spring和 SpringBoot創建 JSPWeb應用程序所需的配置。
Spring需要定義調度程序 servlet,映射和其他支持配置。我們可以使用 web.xml 文件或 Initializer類來完成此操作:
public class MyWebAppInitializer implements WebApplicationInitializer {
@Override
public void onStartup(ServletContext container) {
AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
context.setConfigLocation("com.pingfangushi");
container.addListener(new ContextLoaderListener(context));
ServletRegistration.Dynamic dispatcher = container
.addServlet("dispatcher", new DispatcherServlet(context));
dispatcher.setLoadOnStartup(1);
dispatcher.addMapping("/");
}
}
還需要將 @EnableWebMvc注釋添加到 @Configuration類,并定義一個視圖解析器來解析從控制器返回的視圖:
@EnableWebMvc
@Configuration
public class ClientWebConfig implements WebMvcConfigurer {
@Bean
public ViewResolver viewResolver() {
InternalResourceViewResolver bean
= new InternalResourceViewResolver();
bean.setViewClass(JstlView.class);
bean.setPrefix("/WEB-INF/view/");
bean.setSuffix(".jsp");
return bean;
}
}
再來看 SpringBoot一旦我們添加了 Web啟動程序, SpringBoot只需要在 application配置文件中配置幾個屬性來完成如上操作:
spring.mvc.view.prefix=/WEB-INF/jsp/
spring.mvc.view.suffix=.jsp
上面的所有Spring配置都是通過一個名為auto-configuration的過程添加 Bootweb starter來自動包含的。
這意味著 SpringBoot將查看應用程序中存在的依賴項,屬性和 bean,并根據這些依賴項,對屬性和 bean進行配置。當然,如果我們想要添加自己的自定義配置,那么 SpringBoot自動配置將會退回。
現在我們來看下如何在Spring和Spring Boot中配置Thymeleaf模板引擎。
在 Spring中,我們需要為視圖解析器添加 thymeleaf-spring5依賴項和一些配置:
@Configuration
@EnableWebMvc
public class MvcWebConfig implements WebMvcConfigurer {
@Autowired
private ApplicationContext applicationContext;
@Bean
public SpringResourceTemplateResolver templateResolver() {
SpringResourceTemplateResolver templateResolver = new SpringResourceTemplateResolver();
templateResolver.setApplicationContext(applicationContext);
templateResolver.setPrefix("/WEB-INF/views/");
templateResolver.setSuffix(".html");
return templateResolver;
}
@Bean
public SpringTemplateEngine templateEngine() {
SpringTemplateEngine templateEngine = new SpringTemplateEngine();
templateEngine.setTemplateResolver(templateResolver());
templateEngine.setEnableSpringELCompiler(true);
return templateEngine;
}
@Override
public void configureViewResolvers(ViewResolverRegistry registry) {
ThymeleafViewResolver resolver = new ThymeleafViewResolver();
resolver.setTemplateEngine(templateEngine());
registry.viewResolver(resolver);
}
}
SpringBoot1X只需要 spring-boot-starter-thymeleaf的依賴項來啟用 Web應用程序中的 Thymeleaf支持。 ??但是由于 Thymeleaf3.0中的新功能,我們必須將 thymeleaf-layout-dialect 添加為 SpringBoot2XWeb應用程序中的依賴項。配置好依賴,我們就可以將模板添加到 src/main/resources/templates文件夾中, SpringBoot將自動顯示它們。
為簡單起見,我們使用框架默認的 HTTPBasic身份驗證。讓我們首先看一下使用 Spring啟用 Security所需的依賴關系和配置。
Spring首先需要依賴 spring-security-web和 spring-security-config 模塊。接下來, 我們需要添加一個擴展 WebSecurityConfigurerAdapter的類,并使用 @EnableWebSecurity注解:
@Configuration
@EnableWebSecurity
public class CustomWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("admin")
.password(passwordEncoder()
.encode("password"))
.authorities("ROLE_ADMIN");
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.anyRequest().authenticated()
.and()
.httpBasic();
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
這里我們使用 inMemoryAuthentication來設置身份驗證。同樣, SpringBoot也需要這些依賴項才能使其工作。但是我們只需要定義 spring-boot-starter-security的依賴關系,因為這會自動將所有相關的依賴項添加到類路徑中。
SpringBoot中的安全配置與上面的相同 。
Spring和 SpringBoot中應用程序引導的基本區別在于 servlet。Spring使用 web.xml 或 SpringServletContainerInitializer作為其引導入口點。SpringBoot僅使用 Servlet3功能來引導應用程序,下面讓我們詳細來了解下
Spring支持傳統的 web.xml引導方式以及最新的 Servlet3+方法。
配置 web.xml方法啟動的步驟
Servlet容器(服務器)讀取 web.xml
web.xml中定義的 DispatcherServlet由容器實例化
DispatcherServlet通過讀取 WEB-INF/{servletName}-servlet.xml來創建 WebApplicationContext。最后, DispatcherServlet注冊在應用程序上下文中定義的 bean
使用 Servlet3+方法的 Spring啟動步驟
容器搜索實現 ServletContainerInitializer的類并執行 SpringServletContainerInitializer找到實現所有類 WebApplicationInitializer``WebApplicationInitializer創建具有XML或上下文 @Configuration類 WebApplicationInitializer創建 DispatcherServlet與先前創建的上下文。
Spring Boot應用程序的入口點是使用@SpringBootApplication注釋的類
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
默認情況下, SpringBoot使用嵌入式容器來運行應用程序。在這種情況下, SpringBoot使用 publicstaticvoidmain入口點來啟動嵌入式 Web服務器。此外,它還負責將 Servlet, Filter和 ServletContextInitializerbean從應用程序上下文綁定到嵌入式 servlet容器。SpringBoot的另一個特性是它會自動掃描同一個包中的所有類或 Main類的子包中的組件。
SpringBoot提供了將其部署到外部容器的方式。我們只需要擴展 SpringBootServletInitializer即可:
/**
* War部署
*
* @author SanLi
* Created by 2689170096@qq.com on 2018/4/15
*/
public class ServletInitializer extends SpringBootServletInitializer {
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(Application.class);
}
@Override
public void onStartup(ServletContext servletContext) throws ServletException {
super.onStartup(servletContext);
servletContext.addListener(new HttpSessionEventPublisher());
}
}
這里外部 servlet容器查找在war包下的 META-INF文件夾下MANIFEST.MF文件中定義的 Main-class, SpringBootServletInitializer將負責綁定 Servlet, Filter和 ServletContextInitializer。
最后,讓我們看看如何打包和部署應用程序。這兩個框架都支持 Maven和 Gradle等通用包管理技術。但是在部署方面,這些框架差異很大。例如,Spring Boot Maven插件在 Maven中提供 SpringBoot支持。它還允許打包可執行 jar或 war包并 就地運行應用程序。
在部署環境中 SpringBoot 對比 Spring的一些優點包括:
1、提供嵌入式容器支持
2、使用命令java -jar獨立運行jar
3、在外部容器中部署時,可以選擇排除依賴關系以避免潛在的jar沖突
4、部署時靈活指定配置文件的選項
5、用于集成測試的隨機端口生成
簡而言之,我們可以說 SpringBoot只是 Spring本身的擴展,使開發,測試和部署更加方便。
此外還要注意這里不一定就是正式進入規范的語法。
在我們開發的時候,可能認為應該默認使用 let 而不是 var,這種情況下,對于需要寫保護的變量要使用 const。
然而另一種做法日益普及:默認使用 const,只有當確實需要改變變量的值的時候才使用 let。這是因為大部分的變量的值在初始化后不應再改變,而預料之外的變量的修改是很多 bug 的源頭。
// 例子 1-1
// bad
var foo = 'bar';
// good
let foo = 'bar';
// better
const foo = 'bar';
復制代碼
需要拼接字符串的時候盡量改成使用模板字符串:
// 例子 2-1
// bad
const foo = 'this is a' + example;
// good
const foo = `this is a ${example}`;
復制代碼
可以借助標簽模板優化書寫方式:
// 例子 2-2
let url = oneLine `
www.taobao.com/example/index.html
?foo=${foo}
&bar=${bar}
`;
console.log(url);
復制代碼
oneLine 的源碼可以參考 《ES6 系列之模板字符串》
https://github.com/mqyqingfeng/Blog/issues/109
優先使用箭頭函數,不過以下幾種情況避免使用:
// 例子 3-1
// bad
let foo = {
value: 1,
getValue: () => console.log(this.value)
}
foo.getValue(); // undefined
復制代碼
// 例子 3-2
// bad
function Foo() {
this.value = 1
}
Foo.prototype.getValue = () => console.log(this.value)
let foo = new Foo()
foo.getValue(); // undefined
復制代碼
// 例子 3-3
// bad
const button = document.getElementById('myButton');
button.addEventListener('click', () => {
console.log(this === window); // => true
this.innerHTML = 'Clicked button';
});
復制代碼
// 例子 4-1
// bad
// 1. 創建的屬性會被 for-in 或 Object.keys() 枚舉出來
// 2. 一些庫可能在將來會使用同樣的方式,這會與你的代碼發生沖突
if (element.isMoving) {
smoothAnimations(element);
}
element.isMoving = true;
// good
if (element.__$jorendorff_animation_library$PLEASE_DO_NOT_USE_THIS_PROPERTY$isMoving__) {
smoothAnimations(element);
}
element.__$jorendorff_animation_library$PLEASE_DO_NOT_USE_THIS_PROPERTY$isMoving__ = true;
// better
var isMoving = Symbol("isMoving");
...
if (element[isMoving]) {
smoothAnimations(element);
}
element[isMoving] = true;
復制代碼
魔術字符串指的是在代碼之中多次出現、與代碼形成強耦合的某一個具體的字符串或者數值。
魔術字符串不利于修改和維護,風格良好的代碼,應該盡量消除魔術字符串,改由含義清晰的變量代替。
// 例子 4-1
// bad
const TYPE_AUDIO = 'AUDIO'
const TYPE_VIDEO = 'VIDEO'
const TYPE_IMAGE = 'IMAGE'
// good
const TYPE_AUDIO = Symbol()
const TYPE_VIDEO = Symbol()
const TYPE_IMAGE = Symbol()
function handleFileResource(resource) {
switch(resource.type) {
case TYPE_AUDIO:
playAudio(resource)
break
case TYPE_VIDEO:
playVideo(resource)
break
case TYPE_IMAGE:
previewImage(resource)
break
default:
throw new Error('Unknown type of resource')
}
}
復制代碼
Symbol 也可以用于私有變量的實現。
// 例子 4-3
const Example = (function() {
var _private = Symbol('private');
class Example {
constructor() {
this[_private] = 'private';
}
getName() {
return this[_private];
}
}
return Example;
})();
var ex = new Example();
console.log(ex.getName()); // private
console.log(ex.name); // undefined
復制代碼
// 例子 5-1
[...new Set(array)]
復制代碼
// 例子 5-2
// 根據顏色找出對應的水果
// bad
function test(color) {
switch (color) {
case 'red':
return ['apple', 'strawberry'];
case 'yellow':
return ['banana', 'pineapple'];
case 'purple':
return ['grape', 'plum'];
default:
return [];
}
}
test('yellow'); // ['banana', 'pineapple']
復制代碼
// good
const fruitColor = {
red: ['apple', 'strawberry'],
yellow: ['banana', 'pineapple'],
purple: ['grape', 'plum']
};
function test(color) {
return fruitColor[color] || [];
}
復制代碼
// better
const fruitColor = new Map()
.set('red', ['apple', 'strawberry'])
.set('yellow', ['banana', 'pineapple'])
.set('purple', ['grape', 'plum']);
function test(color) {
return fruitColor.get(color) || [];
}
復制代碼
for...of 循環可以使用的范圍包括:
ES2015 引入了 for..of 循環,它結合了 forEach 的簡潔性和中斷循環的能力:
// 例子 6-1
for (const v of ['a', 'b', 'c']) {
console.log(v);
}
// a b c
for (const [i, v] of ['a', 'b', 'c'].entries()) {
console.log(i, v);
}
// 0 "a"
// 1 "b"
// 2 "c"
復制代碼
// 例子 6-2
let map = new Map(arr);
// 遍歷 key 值
for (let key of map.keys()) {
console.log(key);
}
// 遍歷 value 值
for (let value of map.values()) {
console.log(value);
}
// 遍歷 key 和 value 值(一)
for (let item of map.entries()) {
console.log(item[0], item[1]);
}
// 遍歷 key 和 value 值(二)
for (let [key, value] of data) {
console.log(key)
}
復制代碼
// 例子 7-1
// bad
request(url, function(err, res, body) {
if (err) handleError(err);
fs.writeFile('1.txt', body, function(err) {
request(url2, function(err, res, body) {
if (err) handleError(err)
})
})
});
// good
request(url)
.then(function(result) {
return writeFileAsynv('1.txt', result)
})
.then(function(result) {
return request(url2)
})
.catch(function(e){
handleError(e)
});
復制代碼
// 例子 7-2
fetch('file.json')
.then(data => data.json())
.catch(error => console.error(error))
.finally(() => console.log('finished'));
復制代碼
// 例子 8-1
// good
function fetch() {
return (
fetchData()
.then(() => {
return "done"
});
)
}
// better
async function fetch() {
await fetchData()
return "done"
};
復制代碼
// 例子 8-2
// good
function fetch() {
return fetchData()
.then(data => {
if (data.moreData) {
return fetchAnotherData(data)
.then(moreData => {
return moreData
})
} else {
return data
}
});
}
// better
async function fetch() {
const data = await fetchData()
if (data.moreData) {
const moreData = await fetchAnotherData(data);
return moreData
} else {
return data
}
};
復制代碼
// 例子 8-3
// good
function fetch() {
return (
fetchData()
.then(value1 => {
return fetchMoreData(value1)
})
.then(value2 => {
return fetchMoreData2(value2)
})
)
}
// better
async function fetch() {
const value1 = await fetchData()
const value2 = await fetchMoreData(value1)
return fetchMoreData2(value2)
};
復制代碼
// 例子 8-4
// good
function fetch() {
try {
fetchData()
.then(result => {
const data = JSON.parse(result)
})
.catch((err) => {
console.log(err)
})
} catch (err) {
console.log(err)
}
}
// better
async function fetch() {
try {
const data = JSON.parse(await fetchData())
} catch (err) {
console.log(err)
}
};
復制代碼
// 例子 8-5
// bad
(async () => {
const getList = await getList();
const getAnotherList = await getAnotherList();
})();
// good
(async () => {
const listPromise = getList();
const anotherListPromise = getAnotherList();
await listPromise;
await anotherListPromise;
})();
// good
(async () => {
Promise.all([getList(), getAnotherList()]).then(...);
})();
復制代碼
構造函數盡可能使用 Class 的形式
// 例子 9-1
class Foo {
static bar () {
this.baz();
}
static baz () {
console.log('hello');
}
baz () {
console.log('world');
}
}
Foo.bar(); // hello
復制代碼
// 例子 9-2
class Shape {
constructor(width, height) {
this._width = width;
this._height = height;
}
get area() {
return this._width * this._height;
}
}
const square = new Shape(10, 10);
console.log(square.area); // 100
console.log(square._width); // 10
復制代碼
// 例子 10-1
class Math {
@log
add(a, b) {
return a + b;
}
}
復制代碼
log 的實現可以參考 《ES6 系列之我們來聊聊裝飾器》
// 例子 10-2
class Toggle extends React.Component {
@autobind
handleClick() {
console.log(this)
}
render() {
return (
<button onClick={this.handleClick}>
button
</button>
);
}
}
復制代碼
autobind 的實現可以參考 《ES6 系列之我們來聊聊裝飾器》
// 例子 10-3
class Toggle extends React.Component {
@debounce(500, true)
handleClick() {
console.log('toggle')
}
render() {
return (
<button onClick={this.handleClick}>
button
</button>
);
}
}
復制代碼
debounce 的實現可以參考 《ES6 系列之我們來聊聊裝飾器》
// 例子 10-4
// good
class MyReactComponent extends React.Component {}
export default connect(mapStateToProps, mapDispatchToProps)(MyReactComponent);
// better
@connect(mapStateToProps, mapDispatchToProps)
export default class MyReactComponent extends React.Component {};
復制代碼
// 例子 11-1
// bad
function test(quantity) {
const q = quantity || 1;
}
// good
function test(quantity = 1) {
...
}
復制代碼
// 例子 11-2
doSomething({ foo: 'Hello', bar: 'Hey!', baz: 42 });
// bad
function doSomething(config) {
const foo = config.foo !== undefined ? config.foo : 'Hi';
const bar = config.bar !== undefined ? config.bar : 'Yo!';
const baz = config.baz !== undefined ? config.baz : 13;
}
// good
function doSomething({ foo = 'Hi', bar = 'Yo!', baz = 13 }) {
...
}
// better
function doSomething({ foo = 'Hi', bar = 'Yo!', baz = 13 } = {}) {
...
}
復制代碼
// 例子 11-3
// bad
const Button = ({className}) => {
const classname = className || 'default-size';
return <span className={classname}></span>
};
// good
const Button = ({className = 'default-size'}) => (
<span className={classname}></span>
);
// better
const Button = ({className}) =>
<span className={className}></span>
}
Button.defaultProps = {
className: 'default-size'
}
復制代碼
// 例子 11-4
const required = () => {throw new Error('Missing parameter')};
const add = (a = required(), b = required()) => a + b;
add(1, 2) // 3
add(1); // Error: Missing parameter.
復制代碼
// 例子 12-1
// bad
function sortNumbers() {
return Array.prototype.slice.call(arguments).sort();
}
// good
const sortNumbers = (...numbers) => numbers.sort();
復制代碼
// 例子 12-2
// bad
Math.max.apply(null, [14, 3, 77])
// good
Math.max(...[14, 3, 77])
// 等同于
Math.max(14, 3, 77);
復制代碼
剔除部分屬性,將剩下的屬性構建一個新的對象
// 例子 12-3
let [a, b, ...arr] = [1, 2, 3, 4, 5];
const { a, b, ...others } = { a: 1, b: 2, c: 3, d: 4, e: 5 };
復制代碼
有條件的構建對象
// 例子 12-4
// bad
function pick(data) {
const { id, name, age} = data
const res = { guid: id }
if (name) {
res.name = name
}
else if (age) {
res.age = age
}
return res
}
// good
function pick({id, name, age}) {
return {
guid: id,
...(name && {name}),
...(age && {age})
}
}
復制代碼
合并對象
// 例子 12-5
let obj1 = { a: 1, b: 2,c: 3 }
let obj2 = { b: 4, c: 5, d: 6}
let merged = {...obj1, ...obj2};
復制代碼
將對象全部傳入組件
// 例子 12-6
const parmas = {value1: 1, value2: 2, value3: 3}
<Test {...parmas} />
復制代碼
// 例子 13-1
foo::bar;
// 等同于
bar.bind(foo);
foo::bar(...arguments);
// 等同于
bar.apply(foo, arguments);
復制代碼
如果雙冒號左邊為空,右邊是一個對象的方法,則等于將該方法綁定在該對象上面。
// 例子 13-2
var method = obj::obj.foo;
// 等同于
var method = ::obj.foo;
let log = ::console.log;
// 等同于
var log = console.log.bind(console);
復制代碼
// 例子 14-1
componentWillReceiveProps(newProps) {
this.setState({
active: newProps.active
})
}
componentWillReceiveProps({active}) {
this.setState({active})
}
復制代碼
// 例子 14-2
// bad
handleEvent = () => {
this.setState({
data: this.state.data.set("key", "value")
})
};
// good
handleEvent = () => {
this.setState(({data}) => ({
data: data.set("key", "value")
}))
};
復制代碼
// 例子 14-3
Promise.all([Promise.resolve(1), Promise.resolve(2)])
.then(([x, y]) => {
console.log(x, y);
});
復制代碼
// 例子 14-4
// bad
function test(fruit) {
if (fruit && fruit.name) {
console.log (fruit.name);
} else {
console.log('unknown');
}
}
// good
function test({name} = {}) {
console.log (name || 'unknown');
}
復制代碼
// 例子 14-5
let obj = {
a: {
b: {
c: 1
}
}
};
const {a: {b: {c = ''} = ''} = ''} = obj;
復制代碼
// 例子 14-6
// bad
const spliteLocale = locale.splite("-");
const language = spliteLocale[0];
const country = spliteLocale[1];
// good
const [language, country] = locale.splite('-');
復制代碼
// 例子 14-8
let { foo: baz } = { foo: 'aaa', bar: 'bbb' };
console.log(baz); // "aaa"
復制代碼
// 例子 14-9
function test(input) {
return [left, right, top, bottom];
}
const [left, __, top] = test(input);
function test(input) {
return { left, right, top, bottom };
}
const { left, right } = test(input);
復制代碼
// 例子 15-1
// bad
const something = 'y'
const x = {
something: something
}
// good
const something = 'y'
const x = {
something
};
復制代碼
動態屬性
// 例子 15-2
const x = {
['a' + '_' + 'b']: 'z'
}
console.log(x.a_b); // z
復制代碼
// 例子 16-1
var arr = ["a", , "c"];
var sparseKeys = Object.keys(arr);
console.log(sparseKeys); // ['0', '2']
var denseKeys = [...arr.keys()];
console.log(denseKeys); // [0, 1, 2]
復制代碼
// 例子 16-2
var arr = ["a", "b", "c"];
var iterator = arr.entries();
for (let e of iterator) {
console.log(e);
}
復制代碼
// 例子 16-3
let arr = ['w', 'y', 'k', 'o', 'p'];
let eArr = arr.values();
for (let letter of eArr) {
console.log(letter);
}
復制代碼
// 例子 16-4
// bad
function test(fruit) {
if (fruit == 'apple' || fruit == 'strawberry') {
console.log('red');
}
}
// good
function test(fruit) {
const redFruits = ['apple', 'strawberry', 'cherry', 'cranberries'];
if (redFruits.includes(fruit)) {
console.log('red');
}
}
復制代碼
// 例子 16-5
var inventory = [
{name: 'apples', quantity: 2},
{name: 'bananas', quantity: 0},
{name: 'cherries', quantity: 5}
];
function findCherries(fruit) {
return fruit.name === 'cherries';
}
console.log(inventory.find(findCherries)); // { name: 'cherries', quantity: 5 }
復制代碼
// 例子 16-6
function isPrime(element, index, array) {
var start = 2;
while (start <= Math.sqrt(element)) {
if (element % start++ < 1) {
return false;
}
}
return element > 1;
}
console.log([4, 6, 8, 12].findIndex(isPrime)); // -1, not found
console.log([4, 6, 7, 12].findIndex(isPrime)); // 2
復制代碼
更多的就不列舉了。
舉個例子:
// 例子 17-1
const obj = {
foo: {
bar: {
baz: 42,
},
},
};
const baz = obj?.foo?.bar?.baz; // 42
復制代碼
同樣支持函數:
// 例子 17-2
function test() {
return 42;
}
test?.(); // 42
exists?.(); // undefined
復制代碼
需要添加 @babel/plugin-proposal-optional-chaining 插件支持
// 例子 18-1
a ||= b;
obj.a.b ||= c;
a &&= b;
obj.a.b &&= c;
復制代碼
Babel 編譯為:
var _obj$a, _obj$a2;
a || (a = b);
(_obj$a = obj.a).b || (_obj$a.b = c);
a && (a = b);
(_obj$a2 = obj.a).b && (_obj$a2.b = c);
復制代碼
出現的原因:
// 例子 18-2
function example(a = b) {
// a 必須是 undefined
if (!a) {
a = b;
}
}
function numeric(a = b) {
// a 必須是 null 或者 undefined
if (a == null) {
a = b;
}
}
// a 可以是任何 falsy 的值
function example(a = b) {
// 可以,但是一定會觸發 setter
a = a || b;
// 不會觸發 setter,但可能會導致 lint error
a || (a = b);
// 就有人提出了這種寫法:
a ||= b;
}
復制代碼
需要 @babel/plugin-proposal-logical-assignment-operators 插件支持
a ?? b
// 相當于
(a !== null && a !== void 0) ? a : b
復制代碼
舉個例子:
var foo = object.foo ?? "default";
// 相當于
var foo = (object.foo != null) ? object.foo : "default";
復制代碼
需要 @babel/plugin-proposal-nullish-coalescing-operator 插件支持
const double = (n) => n * 2;
const increment = (n) => n + 1;
// 沒有用管道操作符
double(increment(double(5))); // 22
// 用上管道操作符之后
5 |> double |> increment |> double; // 22
復制代碼
新開了 知乎專欄,大家可以在更多的平臺上看到我的文章,歡迎關注哦~
ES6 系列目錄地址:https://github.com/mqyqingfeng/Blog
ES6 系列預計寫二十篇左右,旨在加深 ES6 部分知識點的理解,重點講解塊級作用域、標簽模板、箭頭函數、Symbol、Set、Map 以及 Promise 的模擬實現、模塊加載方案、異步處理等內容。
如果有錯誤或者不嚴謹的地方,請務必給予指正,十分感謝。如果喜歡或者有所啟發,歡迎 star,對作者也是一種鼓勵。
原鏈接:https://juejin.im/post/5bfe05505188252098022400
*請認真填寫需求信息,我們會在24小時內與您取得聯系。