Vue 3 的概述以及 ES 6 基本语法的介绍_vite vue3 解析es6语法

+ 事件缓存。
+ 基于Proxy的响应式对象。
1. 重构虚拟 DOM

 Vue 3 重写了虚拟 DOM 的实现方法,使得初始渲染/更新可以提速达100%,对于 Vue 2.x 版本的虚拟 DOM 来说,Vue 会遍历 <template> 模板中的所有内容,并根据这些标签生成对应的虚拟 DOM (虚拟 DOM 一般指采用 key/value 对象来保存标签元素的属性和内容),当有内容改变时,遍历虚拟 DOM 来找到变化前后不同的内容,我们称这个过程叫作 diff(different) ,并找到针对这些变化的内容所对应的DOM节点,并改变其内部属性。例如下面这段代码:

 当触发响应式时,遍历所有的 <div> 标签和 <p> 标签,找到 {{count}} 变量对应的 <p> 标签的 DOM 节点,并改变其内容。对于那些纯静态 <p> 标签的节点进行 diff 其实是比较浪费资源的,当节点的数量很少时,表现并不明显,但是一旦节点的数量过大,在性能上就会慢很多。对此,Vue 3 在此基础上进行了优化,主要有:


	+ 标记静态内容,并区分动态内容(静态提升)。
	+ 更新时只 diff 动态的部分。针对上面的代码,Vue 3 中首先会区分出 {{count}} 这部分动态的节点,在进行 diff 时,只针对这些节点进行,从而减少资源浪费,提升性能。
2. 事件缓存

 我们知道在 Vue 2.x 中,在绑定 DOM 事件时,例如@click,这些事件被认为是动态变量,所以每次更新视图的时候都会追踪它的变化,然后每次触发都要重新生成全新的函数。在 Vue 3中,提供了事件缓存对象 cacheHandlers,当 cacheHandlers 开启的时候,@click绑定的事件会被标记成静态节点,被放入 cacheHandlers 中,这样在视图更新时也不会追踪,当事件再次触发时,就无须重新生成函数,直接调用缓存的事件回调方法即可,在事件处理方面提升了 Vue 的性能。未开启 cacheHandlers 编译后的代码如下:

 
```
<div @click="hi">Hello World</div>
//编译后
export function render(\_ctx, \_cache, $props, $setup, Sdata, $options){
	return (\_openBlock(),\_createElementBlock("div", {onClick:_ctx.hi},"Hello World1",/\*PROPS\*/,["onClick"]))
}

```
 开启cacheHandlers编译后的代码如下:

 
```
<div @click="hi">Hello World</div>
// 编译后
export function render(\_ctx, \_cache, Sprops, $setup, Sdata, $options) {
	return (\_openBlock(),\_createElementBlock("div",{onClick:_cache[0] || (_cache[0]=(...args) => (_ctx.hi && _ctx.hi(...args)))},"Hello World1")) 
}

```
 可以看到主要区别在于onClick那一行,直接从缓存中读取了回调函数。
3. 基于 Proxy 的响应式对象

 在 Vue2.x 中,使用 Object.defineProperty)来实现响应式对象,对于一些复杂的对象,需要循环递归地给每个属性增加 getter/setter 监听器,这使得组件的初始化非常耗时,而 Vue 3中,引入了一种新的创建响应式对象的方法 reactive,其内部就是利用 ES6 的 Proxy API 来实现的,这样可以不用的为每个属性来一一进行添加,以减少开销,提升性能,我们会在后续章节具体讲解 Vue 3 的响应式 和 Proxy API。
  • 更小

更小主要体现在包所占容量的大小,我们知道,前端资源一般都属于静态资源,例如JavaSript 文件、HTML 文件等,这些资源都托管在服务器上,用户在使用浏览器访问时,会将这些资源下载下来,所以精简文件包大小是提升页面性能的重要因素。Vue 3 在这方面可以让开发者打包构建出来的资源更小,从而提升性能。

Tree Shaking 是一个术语,通常用于描述移除 JavaScript 上下文中的未引用代码(dead-code),就像一棵大树,将那些无用的叶子都剪掉。它依赖于 ES6 模块语法的静态结构特性,例如 import 和 export ,这个术语和概念在打包工具 Rollup 和 Webpack 中普及开来。例如下面这段ES6代码:

import {get} from'./api.js'
let doSome () =>{
	get ()
}
doSome ()
// api.js
let post =()=>{
	console.log('post')
}
export post
let get = () =>{
	console.log('get')
}
export get

上面的代码中,api.js代码中的 post 方法相关内容是没有被引入和使用的,有了 Tree Shaking 之后,这部分内容是不会被打包的,这就在一定程度上减少了资源的大小。使用Tree Shaking 的原理是引入了 ES6 的模块静态分析,这就可以在编译时正确判断到底加载了什么代码,但是要注意 import 和 export 是 ES6 原生的,而不是通过 Babel 或者 Webpack 转化的。
在 Vue 3中,对代码结构进行了优化,让其更加符合 Tree Shaking 的结构,这样使用相关的 API 时,就不会把所有的都打包进来,只会打包用户用到的API,例如:

<!-- vue 2.x-->
import Vue from 'vue'
new Vue()
Vue.nextTick(()=>())
const obj = Vue.observable(())

<1-- vue 3.x -->
import ( nextTick, observable,createApp ) from 'vue'
nextTick(()=>())
const obj = observable(1))
createApp(())

同理,例如 、 和 等内置组件,如果没有使用,也不会被打包到资源中。

  • 更易于维护

    1. 从Flow迁移到TypeScript

    TypeScript 是微软开发的一个开源的编程语言,通过在 JavaScript 的基础上添加静态类型定义构建而成,其通过 TypeScript 编译器或 Babel 转译为 JavaScript 代码,可运行在任何浏览器和操作系统上。TypeScript 引入了很多新的特性,例如类型监测、接口等,这些特性在框架源码的维护上有很大的提升。

    在Vue 3的源码结构层面,从 Flow 改成了 TypeScript 来编写,Flow 是一个静态类型检测器,有了它就可以在 JavaScript 运行前找出常见的变量类型的 bug,类似于Java语言中给变量强制指定类型,它的功能主要包括:

      + 自动类型转换。
      + null引用。
      + 处理 undefined is not a function。例如:
    
    // @flow
    function foo(x: number): number {
    	return x + 10
    }
    foo('hi') //参数x须为number类型,否则会报错
    
    错误信息:
    '[flow] string (This type is incompatible with number See also: function call)'
    
    

    上面这段代码采用了Flow后,如果类型不对就会报错。一般来说,对于 JavaScript 源码框架,引入类型检测是非常重要的,不仅可以减少 bug 的产生,还可以规范一些接口的定义,这些特性和 TypeScript 非常吻合,所以在 Vue 3 中直接采用了 TypeScript 来进行重写,从源码层面来提升项目的可维护性。
    2. 源代码目录结构遵循 Monorepo

    Monorepo 是一种管理代码的方式,它的核心观点是所有的项目在一个代码仓库中,但是代码分割到一个个小的模块中,而不是都放在 src 这个目录下。这样的分割,使得每个开发者大部分时间只是工作在少数的几个文件夹内,并且也只会编译自己负责的模块,不会导致一个 IDE 打不开太大的项目之类的事情,这样很多事情就简单了很多。

    目前很多大型的框架(例如 Babel、React、Angular、Ember、Meteor、Jest等) 都采用了 Monorepo 这种方式来进行源码的管理,当然在自己的业务项目中,也可以使用 Monorepo 来管理代码。

1.4.2 新特性初体验
  • 组合式API

在 Vue 2.x 中,组件的主要逻辑是通过一些配置项来编写,包括一些内置的生命周期方法或者组件方法,例如下面的代码:

export default{
	name: 'test',
	components:{},
	Props:{},
	data(){
		return {}
	},
	created(){},
	mounted(){},
	watch:{},
	methods:{}
}

上面的代码中,这些基于配置的组件写法称为 Options API (配置式API),Vue 3 的一大核心新特性是引入了 Composition API(组合式API),这使得组件的大部分内容都可以通过 setup方法进行配置。将上述代码改造成组合式 API,代码如下:

import{onMounted, reactive,watch} from 'vue'
export default{
	props:{
		name:String,
	},
	name: 'test',
	components:{},
	setup (props,ctx){
		console.log(props.name)
		console.log('created')
		const data = reactive({
			a:1
		})
		watch{
			() => data.a,
			(val, oldVal) => {
				console.log(val)
			}
		}
		onMounted(()=>{
		})
		const myMethod = (obj) =>{
		}
		retrun{
			data,
			myMethod
		}
	}
}

上面的代码采用了ES6的语法,并且使用了 Vue3 的 Composition API 中的 setup 方法,可能读者有些看不懂,没关系,我们会在后续章节中具体讲解。

  • 内置组件 Teleport、Suspense 和 Fragments 片段

和 都是 Vue 3里面新增的内置组件,这里把内置组件称作可以直接写在里面,而不需要格外引入的组件,例如 就是一个内置组件。而 Fragments 是一种新的特性,让开发者可以不用在 中强制包裹一个根元素,关于 和 的内容会在第3章深入讲解。

  • 服务端渲染

在服务端渲染方面,Vue 3 优化了返回 HTML 字符串的逻辑。在 Vue2.x 中,所有的节点(包括一些静态节点)在服务端返回时都会转换为虚拟 DOM,再转换成 HTML 字符串返回给浏览器;Vue 3 则将静态节点剥离成字符串,这部分内容不会转换成虚拟 DOM,而是直接拼接返回,在效率上进行了提升。

Vue 2.x 的服务端渲染代码如下:

<div>
	<div>abc</div>
	<div>abc</div>
	<div>abc</div>
	<div>{{msgl}}</div>
</div>
//编译后
function anonymous(){
	var _vm = this;
	var _h = _vm.$createElement;
	var _c = _vm._self._c || _h;
	return \_c('div', [_vm.\_ssrNode("<div>abc</div> <div>abc</div> <div>abc</div> <div>" + _vm.\_ssrEscape(_vm.\_s(_vm.msg))+"</div>")])
}

Vue 3 的服务端渲染代码如下:

<div>
	<div>abc</div>
	<div>abc</div>
	<div>abc</div>
	<div>{{msg}}</div>
</div>
// 编译后
export function ssrRender(\_ctx, \_push, \_parent, attrs, $props, $setup, $data, $options){
	const _cssVars= { style: { color: _ctx.color }}
	\_push('<div${ \_ssrRenderAttrs(\_mergeProps(_attrs, _cssVars))}>xdiv>abc</div><div>abc</div><div>abc</div><div>${\_ssrInterpolate(_ctx.msg)}</div></div>`)
}

  1. Vite

伴随着 Vue 3,Vue 团队也推出了自己的开发构建工具 Vite,可以在一定程度上取代 Vue Cli 和 webpack-dev-server 的功能。基于此,Vite 主要有以下特性:

* 快速的冷启动
* 即时的模块热更新
* 真正的按需编译Vite 在开发环境下基于浏览器原生 ES6 Modules 开发,在生产环境下基于 Rollup 打包,我们会在后续章节深入讲解 Vite 的相关使用。

第 2 章 ES 6 语言基础

ES 6 是一次重大的版本升级,与此同时,由于 ES 6 秉承着最大化兼容已有代码的设计理念,过去编写的 JS 代码还能正常运行。事实上,许多浏览器已经支持部分 ES 6 特性,并继续努力实现其余特性。这意味着,在一些已经实现部分特性的浏览器中,开发者符合标准的 JavaScript 代码已经可以正常运行,可以更加方便地实现很多复杂的操作,提高开发人员的工作效率。

由于移动端操作系统和浏览器兼容性问题的限制,虽然大部分机型原生就支持 ES 6语法的JavaScript,但是仍有一部分市场占有率较低的机型无法支持 ES 6 语法,例如 Android 系统 4.4 及以下版本和 iOS 系统 8.4 及以下版本。因此,为了项目的健壮性和更强的适配性,会采用 Node.js的 Babel 工具来将 ES 6 代码转换成兼容性更强的 ES 5 代码。

以下是 ES 6 排名前10位的最佳特性列表(排名不分先后):

  • Default Parameters(默认参数)
  • Template Literals(模板文本)
  • Multi-line Strings(多行字符串)
  • Destructuring Assignment(解构赋值)
  • Enhanced Object Literals(增强的对象文本)
  • Arrow Functions(箭头函数)
  • Promises
  • Block-Scoped Constructs Let and Const (块作用域构造 Let 和 Const )
  • Classes(类)
  • Modules(模块)

1. 块作用域构造 Let 和 Const

在 ES 6 语法中,新增了 let 和 const 来声明变量,在 ES 6 之前,ES 5 中只有全局作用域和函数作用域,代码如下:

if(true){
	var a ='Tom'
}
console.log('a',a) // Tom

作用域是一个独立的地盘,让变量不外泄出去,但是上面的代码中的变量 a 就作为全局作用域外泄了出去,所以此时 JavaScript 没有区块作用域(或称为块级作用域)的概念。

在 ES 6 中加入区块作用域之后,代码如下:

if(true){
	let a ='Tom'
}
console.log('a',a)// Uncaught ReferenceError: a s not defined

let 和 var 都可以用来声明变量,但是在 ES 6 中,有下面一些区别:

  • 使用 var 声明的变量没有区块的概念,可以跨块访问
  • 使用 let 声明的变量只能在区块作用域中访问,不能跨块访问

在相同的作用域下,使用 var 和 let 具有相同的效果,建议在 ES 6 语法中使用 let 来声明变量,这样可以更加明确该变量所处的作用域。

const 表示声明常量,一般用于一旦声明就不再修改的值,并且const 声明的常量必须经过初始化,代码如下:

const a=1
a =2 // Uncaught TypeError: Assignment to constant variable
const b // Uncaught SyntaxError: Missing initializer in const declaration

总结一下,如果在 ES 5 中习惯了使用 var 来声明变量,在切换到 ES 6 时,就需要思考一下变量的用途和类型,选择合适的 let 和 const 来使代码更加规范和语义化。

2. 模板字面量

ES 6 引入了模板字面量(Template Literals),主要通过多行字符串(Multi-line Strings)和字符串占位符对字符串的操作进行增强。

多行字符串

ES 5 中,如果一个字符串面量要分为多行,那么可以采用以下两种方法来实现。

(1)、在一行的结尾添加反斜杠表示承接上一行的代码。这种方式是利用JavaScript的语法Bug来实现的:

//多行字符串
var roadPoem = "江南好,\
风景旧曾谙。";

(2)、使用加号来拼接字符串。

//多行字符串
var roadPoem = "江南好,风景旧曾谙。"
+ "日出江花红胜火,春来江水绿如蓝。"
+ "能不忆江南?";

ES 6 的多行字符串是一个非常实用的功能。模板字面量的基础语法就是使用反引号替换字符串的单、双引号。例如:

let roadpoem = `江南好,风景旧曾谙。`;

如果需要在字符串中使用反引号,可以使用反斜杠将它转义。

let roadPoem = `江南好,\`风景旧曾谙。`;

ES 6 中,使用模板字面量语法可以非常方便地创建多行字符串。

//多行字符串
let roadPoem = `江南好,风景旧曾谙。
日出江花红胜火,春来江水绿如蓝。`;
console.log(roadPoem);

输出结果为:

江南好,风景旧曾谙。
日出江花红胜火,春来江水绿如蓝。

字符串占位符

在一个模板字面量中,可以将 JavaScript 变量或 JavaScript 表达式嵌入占位符并将其作为字符的一部分输出到结果中。

ES 6 中,占位符是使用语法 ${NAME} 的,并将包含的NAME变量或者表达式放在反号中:

let name = "xiaoming";
let names = `zhang ${name}`;
let price = 18.8;
let num = 8;
let total = `商品的总价是:${price \* num}`;

由于模板字面量本身也是 JavaScript 表达式,因此也可以在一个模板字面量中嵌入另一个模字面量。

let price = 10;
let num = 8;
let total = `经过计算,${
`商品的总价是:${price ★ num}`
}`;
console.log(total);

输出结果为:

经过计算,商品的总价是:80

3. 默认参数和 rest 参数

ES 5 中,JavaScript 定义默认参数的方式如下:

//以前的 JavaScript 定义默认参数的方式
function funl(height, color, url){
	var height = height || 150;
	var color = color || "red";
	var url = url || "http://www.baidu.com";
	...
}

ES 6 中,可以直接把默认值放在函数声明中:

//新的 JavaScript 定义方式
function fun2(height = 50, color = "red", url = "http://www.baidu.com"){
	...
}

ES 6 中,声明函数时,可以为任意参数指定默认值,在已指定默认值的参数后还可以继续声明无默认值的参数。

function fun3(height = 50, color = "red", ur1){}

在这种情况下,只有在没有为 height 和 color 传值,或者主动为它们传入 undefined 时才会使用它们的默认值。

ES 5 中,无论在函数定义中声明了多少形参,都可以传入任意数量的参数,在函数内部可以通过 arguments 对象接收传入的参数。

function data(){
	console.log(arguments);
}
data("li","cc";

ES 6 中引入了 rest 参数,在函数的命名参数前添加了3个点,用于获取函数的实参。rest 参数是一个数组,包含自它之后传入的所有参数,通过这个数组名就可以逐一访问里面的参数。

function data(...args){
	console.log(args);
}
data("苹果","香蕉","橘子");

rest参数必须放到参数最后位置

function fn(a, b,...args){
	console.log(a);
	console.log(b);
	console.log(args);
}
fn(100, 200, 300, 400, 500, 600);

4. 解构赋值

ES 5 中,如果需要从某个对象或者数组中提取需要的数据赋给变量,可以采用如下方式:

let goods = {
	name : "苹果",
	city : "烟台",
	price : "烟台"
} 
//提取对象中的数据赋给变量
let name = goods.name;
let city = goods.city;
let price = goods.price;
//提取数组中的数据赋给变量
let arr= [100, 200, 300, 400];
let a1 = arr[0], a2 = arr[1], a3 = arr[2], a4 =arr[3];

ES 6 中,通过使用解构赋值的功能,可以从对象和数组中提取数值,并对变量进行赋值数

对象解构

对象解构的方法是在一个赋值操作符的左边放置一个对象字面量。

let goods = {
	name : "苹果",
	city : "烟台",
	price : "烟台"
}
//使用解构赋值的功能
let {name,city,price} = goods;

如果变量已经声明了,之后想要用解构语法给变量赋值,则需要把整个解构赋值语句放到圆括号中。

let goods = {
	name : "苹果",
	city : "烟台",
	price : "烟台"
}
//先声明变量,然后解构赋值
let name,city,price;
({name,city,pzice}= goods) ;

数组解构

因为没有对象属性名的问题,所以数组解构相对比较简单,使用方括号即可。

let arr = [100,200, 300, 400];
let [a1,a2,a3,a4] = arr;

由于变量值是根据数组中元素的顺序进行选取的,因此,如果需要获取指定位置的元素值,可以只为该位置的元素提供变量名。

let arr = [100,200,300,400];
//获取第 4 个位置的元素
let [,,,a4] = arr;
console.log(a4); //输出 400

和对象解构不同,如果为已经声明过的变量进行数组解构赋值,不需要把整个解构赋值语句到一个圆括号中。

let arr =[100,200,300,400];
let a1, a2, a3, a4;
[a1, a2, a3, a4] = arr;

5. 展开运算符

展开运算符(Spread Operator)也是3个点,允许一个表达式在某处展开。展开运算符在多个参数(用于函数调用)、多个元素(用于数组字面量)或者多个变量(用于解构赋值)的地方可以使用。

在函数调用中使用展开运算符

ES 5 中可以使用 apply 方法将一个数组展开成多个参数:

function test(a, b,c) {}
var args = [100, 200, 300};
test.apply(null, args);

上面的代码中,把args数组当作实参传递给了a、b和c。

ES 6 中可以更加简洁地来传递数组参数:

function test(a,b,c) {}
var args = [100, 200, 300];
test(...args) ;

这里使用展开运算符把 args 直接传递给 test 函数。

在数组字面量中使用展开运算符

ES 6 中,可以直接加一个数组并合并到另一个数组中:

var arr1 = ['a', 'b', 'c'];
var arr2 = [...arr1, 'd', 'e']; //['a','b','c','d','e']

展开运算符也可以用在 push 函数中,可以不需要再使用 apply 函数来合并两个数组:

var arr1 = ['a', 'b', 'c'];
var arr2 = ['d', 'e'];
arrl.push(...arr2); //['a','b','c','d','e']

用于解构赋值

解构赋值也是 ES 6 中新添加的一个特性,这个展开运算符可以用于部分情景:

let [argl,arg2,...,arg3]=[1, 2, 3, 4];
argl //1
arg2 //2
arg3 //['3', '4']

展开运算符在解构赋值中的作用跟之前的作用看上去是相反的,它将多个数组项组合成了一个新数组。
不过要注意,解构赋值中的展开运算符只能用在最后。

let [arg1,...,arg2,arg3] = [1, 2, 3, 4]; //报错

类数组对象变成数组

展开运算符可以将一个类数组对象变成一个真正的数组对象:

var list = document.getElementsByTagName('div');
var arr = [...list];

list 是类数组对象,这里通过使用展开运算符使其变成了数组。

6. 增强的对象文本

ES 6 添加了一系列功能来增强对象文本,从而使得处理对象更加轻松。

通过变量进行对象初始化

ES 5 中,对象的属性通常是由具有相同名称的变量创建的。例如:

var
	a = 100,b = 200, c = 300;
	obj = {
		a : a,
		b : b,
		c : c
	};
// obj.a = 100, obj.b = 200, obj.c = 300

ES 6 中,简化如下:

const
	a = 100, b = 200, c = 300;
	obj = {
		a
		b
		c
	};

简化定义对象方法

ES 5 中,定义对象的方法需要 function 语句。例如:

var lib = {
	sum : function(a, b) { return a + b;},
	mult : function(a, b) { return a \* b;}
};
console.log( lib.sum(100, 200)); // 300
console.log( lib.mult(100, 200)); // 20000

ES 6 中,定义对象的方法简化如下:

const lib = {
	sum(a, b) { return a + b; },
	mult(a, b) { return a \* b; }
};
console.log( lib.sum(100,200));// 300
console.log( lib.mult(100, 200));//20000

这里不能使用 ES 6 的箭头函数(=>),因为该方法需要一个名称。如果直接命名每个方法,则可以使用箭头函数(=>)。例如:

const lib = {
	sum : (a, b) => a + b,
	mult : (a, b)=> a \* b
};
console.log( lib.sum(100,200));// 300
console.log( lib.mult(100, 200)); //20000

动态属性键

ES 5 中,虽然可以在创建对象之后添加变量,但是不能使用变量作为键名称。例如

var
	key1 = 'one',
	obj = {
		two : 200,
		three : 300
	};
obj[key1] = 100;
//表示obj.one = 100,obj.two = 200, obj.three = 300

通过在方括号(Ⅱ)内放置表达式,可以在ES6中动态分配对象键。例如:

const
	key1 = 'one',
	obj = {
		[key1]: 100,
		two : 200,
		three : 300
	}
//表示obj.one = 100, obj.two = 200, obj.three = 300

解构对象属性中的变量

ES 5 中,可以将对象的属性值提取到另一个变量中。例如:

var myobject = { 
	one : '洗衣机',
	two : '冰箱',
	three : '空调'
);
var
	one = myobject.one,//洗衣机
	two = myobject.two,//冰箱
	three = myobject.three; //空调

ES 6 中,通过解构可以创建与等效对象属性同名的变量。例如:

var myobject = { 
	one : '洗衣机',
	two : '冰箱',
	three : '空调'
);
const { one, two, three } =  myobject;
//表示one = '洗衣机',two = '冰箱',three = '空调'

7. 箭头函数

ES 6 新增了使用“箭头”声明函数,代码如下:

let f = v => v
//等同于
var f = function (v){
	return v
}

如果箭头函数不需要参数或需要多个参数,就使用一个圆括号代表参数部分,当函数的内容只有返回语句时,可以省去大括号和 return 指令,代码如下:

let f = () => 5
//等同于
var f = function () { return 5 }
	
let sum = (num1, num2) => num1 + num2;
// 等同于
var sum = function(numl, num2) {
	return numl + num2
}

如果箭头数的内容部分多于一条语句,就要用大括号将它们括起来,并且使用 return 语句返回,代码如下:

let sum = (numl, num2) =>{
	let num = 0;
	return num1 + num2 + num;
}

箭头函数会默认绑定外层的上下文对象 this 的值,因此在箭头函数中,this 的值和外层的this 是一样的,不需要使用 bind 或者 call 的方法来改变函数中的上下文对象,例如下面的代码:

mounted () {
	this.foo =1
	setTimeout(function(){ // 打印出1
	console.log(this.foo)
	}.bind(this),200)
}
//相当于
mounted(){
	this.foo = 1
	setTimeout(()
		console.log(this.foo) // 同样打印出1
	),200)
}

上面的代码中,在 Vue.js 的 mounted 方法中,this 指向当前的 Vue 组件的上下文对象,如果想要在 setTimeout 的方法中使用 this 来获取当前 Vue 组件的上下文对象,那么非箭头函数需要使用 bind,箭头函数则不需要。

  1. 对象属性和方法的简写

ES 6 允许在大括号中直接写入变量和函数,作为对象的属性和方法,这样的书写更加简洁,代码如下:

const foo = 'bar'
const baz = {foo}
// 等同于
const baz = {foo: 'bar'}
console.log(baz) // {foo: "bar"}

对象中如果含有方法,也可以将function关键字省去,代码如下:

{
	name: 'item'
	data () {
		return {
			name: 'bar'
		}
	}
	mounted () {
	},
	methods: {
		clearSearch () {
		}
	}
}
//相当于
{
	name: 'item'
	data : function(){
		return {
			name: 'bar'
		}
	}
	mounted : function() {
	},
	methods: {
		clearSearch : function() {
		}
	}
}

在上面的代码中,展示了采用 ES 6 语法来创建 Vue 组件所需的方法和属性,包括 name 属性、mounted 方法、data 方法等,是后面实战项目中经常使用的写法。

8. Modules (模块)

ES 6 版本之前,JavaScript 一直没有模块(Module)体系,无法将一个大程序拆分成互相依赖的小文件,再用简单的方法拼装起来。其他语言都有这项功能,比如 Ruby 的require、 Python 的 import 甚至就连 CSS 都有 import ,但是 JavaScript 任何这方面的支持都没有,这对开发大型的、复杂的项目形成了巨大障碍。

好在广大的 JavaScript 程序员自己制定了一些模块加载方案,主要有 CommonJS 和 AMD 两种。前者用于 Node.js 服务器,后者用于浏览器。

import 和 export

随着 ES 6 的到来,终于原生支持了模块化功能,即 import 和 export ,而且实现得相当简单,完全可以取代 CommonJS 和 AMD 规范成为浏览器和服务器通用的模块化解决方案。

在 ES 6 的模块化系统中,一个模块就是一个独立的文件,模块中的对外接口采用 export 关键字导出,可以将 export 放在任何变量、函数或类声明的前面,从而将它们暴露给外部代码使用,代码如下:

export var name = "小明";
export let age = 20;
//上面的写法等价于下面的写法
var name = "小明”;
let age = 20;
export {
	name:name,
	age:age
}
// export 对象简写的方式
export {name,age}

要导出函数,需要在函数前面加上 export 关键字:

export function sum(numl,num2){
	return numl + num2;
}
//等价于
let sum = function (numl,num2){
	return numl + num2; 
}
export sum 

所以,如果没有通过 export 关键字导出,在外部就无法访问该模块的变量或者函数。 有时会在代码中看到使用 export default,它和 export 具有同样的作用,都是用来导出对外提供接口的,但是它们之间还有一些区别:

  • export default 用于规定模块的默认对外接口,并且一个文件只能有一个 export default,而 export可以有多个
  • 通过 export 方式导出,在导入时要加{},export default 则不需要。

在一个模块中可以采用 import 来导入另一个模块 export 的内容。导入含有多个 export 的内存,可以采用对象简写的方式,也是现在使用比较多的方式,代码

// other.js
var name = "小明"


### 最后

除了简历做到位,面试题也必不可少,整理了些题目,前面有117道汇总的面试到的题目,后面包括了HTML、CSS、JS、ES6、vue、微信小程序、项目类问题、笔试编程类题等专题。



  ![](https://img-blog.csdnimg.cn/img_convert/64ce8432d0f753e43f93972ad19fcd72.png)


![](https://img-blog.csdnimg.cn/img_convert/d508b1ae6a5e7d5e7d5daf668e9eccea.png)

  • 16
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值