前端学习
2021-07-19 11:26:59 85 举报
AI智能生成
前端学习知识总结
作者其他创作
大纲/内容
参考文章
https://www.processon.com/view/5c51418fe4b0fa03ceab8ca0?fromnew=1#map
https://www.processon.com/view/5ece2c93f346fb69071e1a5e?fromnew=1#map
https://www.processon.com/view/56fa2d73e4b064fdbce85a39?fromnew=1#map
原生
完整的JavaScript
核心(ECMAScript)
由ECMA-262定义并提供核心功能。
<script>元素
动态加载脚本
默认情况下,
动态添加<script>元素是以异步方式加载的,相当于添加了async属性。不过这样做可能会
有问题,因为所有浏览器都支持createElement()方法,但不是所有浏览器都支持async属性。因此,
如果要统一动态脚本的加载行为,可以明确将其设置为同步加载
动态添加<script>元素是以异步方式加载的,相当于添加了async属性。不过这样做可能会
有问题,因为所有浏览器都支持createElement()方法,但不是所有浏览器都支持async属性。因此,
如果要统一动态脚本的加载行为,可以明确将其设置为同步加载
let script = document.createElement('script');
script.src = 'gibberish.js';
script.async = false;
document.head.appendChild(script);
script.src = 'gibberish.js';
script.async = false;
document.head.appendChild(script);
预加载资源
过rel="preload"进行内容预加载
例子:<link rel="preload" href="gibberish.js">
现代Web应用程序通常
将所有JavaScript引用放在<body>元素中的页面内容后面
将所有JavaScript引用放在<body>元素中的页面内容后面
把所有JavaScript
文件都放在<head>里,也就意味着必须把所有JavaScript代码都下载、解析和解释完成后,才能开始渲
染页面(页面在浏览器解析到<body>的起始标签时开始渲染)。对于需要很多JavaScript的页面,这会
导致页面渲染的明显延迟,在此期间浏览器窗口完全空白。
文件都放在<head>里,也就意味着必须把所有JavaScript代码都下载、解析和解释完成后,才能开始渲
染页面(页面在浏览器解析到<body>的起始标签时开始渲染)。对于需要很多JavaScript的页面,这会
导致页面渲染的明显延迟,在此期间浏览器窗口完全空白。
文档对象模型(DOM)
提供与网页内容交互的方法和接口。
浏览器对象模型(BOM)
提供与浏览器交互的方法和接口。
String
字符字面量
\0 空字符
\' 单引号
\" 双引号
\\ 反斜杠
\n 换行
\r 回车
\v 垂直制表符
\t 水平制表符
\b 退格
\f 换页
\uXXXX unicode 码
\u{X} ... \u{XXXXXX} unicode codepoint
\xXX Latin-1 字符(x小写)
\' 单引号
\" 双引号
\\ 反斜杠
\n 换行
\r 回车
\v 垂直制表符
\t 水平制表符
\b 退格
\f 换页
\uXXXX unicode 码
\u{X} ... \u{XXXXXX} unicode codepoint
\xXX Latin-1 字符(x小写)
原始字符串
使用默认的String.raw标签函数
console.log(String.raw`\u00A9`); // \u00A9
Symbol
预处理指令
文档模式
混杂模式(quirks mode)
省略文档开头的doctype声明
在不同浏览器中的差异非常大,不使用黑科技基本上就没有浏览器一致性可言。
标准模式(standards mode)
有文档开头的doctype声明
严格模式
"use strict"
是一种不同的JavaScript解析和执行模型,ECMAScript 3的一些不规范写法在这种模式下会被处理,对于不安全的活动将抛出错误
事件冒泡与捕获、默认事件
事件冒泡与捕获
https://www.cnblogs.com/Vincent-yuan/p/12514137.html
事件捕获阶段
事件从祖先元素往子元素查找(DOM树结构),直到捕获到事件目标 target。在这个过程中,默认情况下,事件相应的监听函数是不会被触发的
box1.addEventListener("click", function () {
alert("捕获 box3");
}, true);
alert("捕获 box3");
}, true);
window --> document --> html--> body --> 父元素、子元素、目标元素。
事件目标
当到达目标元素之后,执行目标元素该事件相应的处理函数。如果没有绑定监听函数,那就不执行。
事件冒泡阶段
事件从事件目标 target 开始,从子元素往冒泡祖先元素冒泡,直到页面的最上一级标签。
以下事件不冒泡:blur、focus、load、unload、onmouseenter、onmouseleave
box1.onclick = function (event) {
alert("冒泡 child");
event = event || window.event;
console.log(event.bubbles); //打印结果:true。说明 onclick 事件是可以冒泡的
}
alert("冒泡 child");
event = event || window.event;
console.log(event.bubbles); //打印结果:true。说明 onclick 事件是可以冒泡的
}
阻止冒泡
box3.onclick = function (event) {
alert("child");
//阻止冒泡
event = event || window.event;
if (event && event.stopPropagation) {
event.stopPropagation();
} else {
event.cancelBubble = true;
}
}
alert("child");
//阻止冒泡
event = event || window.event;
if (event && event.stopPropagation) {
event.stopPropagation();
} else {
event.cancelBubble = true;
}
}
应用
事件代理
https://www.cnblogs.com/leftJS/p/10948138.html
将事件处理器绑定到一个父级元素上,避免了频繁的绑定多个子级元素,依靠事件冒泡机制与事件捕获机制,子级元素的事件将委托给父级元素
阻止事件冒泡,阻止默认事件,event.stopPropagation()和event.preventDefault(),return fal的区别
preventDefault
阻止默认行为
场景
阻止链接
阻止表单提交
JS引擎的执行机制
文章
https://segmentfault.com/a/1190000012806637#2
https://www.cnblogs.com/amiezhang/p/11349450.html
https://www.cnblogs.com/wangziye/p/9566454.html
https://www.cnblogs.com/shcrk/p/9325779.html
分类
宏任务macrotask
代码块 > setImmediate > MessageChannel > setTimeout / setInterval
微任务microtask
process.nextTick > Promise = MutationObserver
原型和原型链
原型规则
所有的引用类型(数组、对象、函数)都可以自定义添加属性,除了“null”)
所有的引用类型都有自己的隐式原型(proto)属性,该属性值也是一个普通的对象
函数都有自己的显式原型(prototype)属性
所有的引用类型的隐式原型都指向对应构造函数的显示原型
使用引用类型的某个自定义属性时,如果没有这个属性,会去该引用类型的__proto__(也就是对应构造函数的prototype)中去找
图解
参考文档
说明
图解
Object和Function的原型链关系图
面试题
function this指向
在函数中this到底取何值,是在函数真正被调用执行的时候确定的,函数定义的时候确定不了。因为this的取值是执行上下文环境的一部分,每次调用函数,都会产生一个新的执行上下文环境。
apply、call、bind
相同点
都是用来改变函数的this对象的指向的
第一个参数都是this要指向的对象
都可以利用后续参数传参
不同点
bind是返回对应函数,便于稍后调用,apply、call是立即调用;
call和bind把第二个以后传递进来的实参传递给函数,apply把一个数组(或者类数组)传递给函数
手写
判断变量类型方式
es6
文章
https://www.cnblogs.com/ainyi/p/8537027.html
https://www.cnblogs.com/kreo/p/11069640.html
https://es6.ruanyifeng.com/
知识点
let 和 const
1.都不能重复声明
2.都存在块级作用域问题
3.只在声明所在的块级作用域内有效。
2.都存在块级作用域问题
3.只在声明所在的块级作用域内有效。
基础用法
所声明的变量,只在let命令所在的代码块内有效
for (let i = 0; i < 10; i++) {
a[i] = function () {
console.log(i);
};
}
a[i] = function () {
console.log(i);
};
}
变量i是let声明的,当前的i只在本轮循环有效,所以每一次循环的i其实都是一个新的变量
JavaScript 引擎内部会记住上一轮循环的值,初始化本轮的变量i时,就在上一轮循环的基础上进行计算。
for (let i = 0; i < 3; i++) {
let i = 'abc';
console.log(i);
}
// abc
// abc
// abc
let i = 'abc';
console.log(i);
}
// abc
// abc
// abc
for循环还有一个特别之处,就是设置循环变量的那部分是一个父作用域,而循环体内部是一个单独的子作用域。
函数内部的变量i与循环变量i不在同一个作用域,有各自单独的作用域。
不存在变量提升
var命令会发生“变量提升”现象,即变量可以在声明之前使用,值为undefined
let命令改变了语法行为,它所声明的变量一定要在声明后使用,否则报错。
暂时性死区
tmp = 'abc'; // ReferenceError
let tmp;
let tmp;
不允许重复声明
function func(arg) {
let arg;
}
func() // 报错
function func(arg) {
{
let arg;
}
}
func() // 不报错
let arg;
}
func() // 报错
function func(arg) {
{
let arg;
}
}
func() // 不报错
解构赋值
ES6 允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构
let [foo,[[bar],[baz]]] = [111,[[222],[333]]];
let [head,...foot] = [1,2,3,4];
// 如果变量名与属性名不一致,必须写成下面这样
let obj = {first:'hello',last:'world'};
// first ---> f,那么此时f就是first,而不是undefined了,有点类似别名的概念
let {first:f,last} = obj;
console.log(f,last); // hello world
let obj = {first:'hello',last:'world'};
// first ---> f,那么此时f就是first,而不是undefined了,有点类似别名的概念
let {first:f,last} = obj;
console.log(f,last); // hello world
let x = 1;
let y = 2;
[x, y] = [y, x];
let y = 2;
[x, y] = [y, x];
复制数组
// ES6实现的数组的深拷贝方法1
var arr1 = [1,2,3];
var arr2 = Array.from(arr1);
var arr1 = [1,2,3];
var arr2 = Array.from(arr1);
// ES6实现的数组的深拷贝方法2
var arr1 = [1,2,3];
// 超引用拷贝数组
var arr2 = [...arr1];
var arr1 = [1,2,3];
// 超引用拷贝数组
var arr2 = [...arr1];
function show(...args){
// 此时这个形式参数就是一个数组,我们可以直接push东西进来,如下
args.push(5);
console.log(args);
}
// 调用
show(1,2,3,4); // [1, 2, 3, 4, 5]
// 此时这个形式参数就是一个数组,我们可以直接push东西进来,如下
args.push(5);
console.log(args);
}
// 调用
show(1,2,3,4); // [1, 2, 3, 4, 5]
复制对象
//Object.assign 就是进行对象的浅拷贝
var source={ age:18,height:170,className:"3年2班" }
//克隆一个新对象出来
var newObj=Object.assign({},source);
console.log(newObj);
var source={ age:18,height:170,className:"3年2班" }
//克隆一个新对象出来
var newObj=Object.assign({},source);
console.log(newObj);
var car={ brand:"BMW",price:"368000",length:"3米" }
//克隆一个跟car完全一样的对象出来:
var car2={ ...car }
console.log(car2);
//新车子,跟car的长度不同,其他相同
var car3={ ...car,length:"4米" }
console.log(car3);
//克隆一个跟car完全一样的对象出来:
var car2={ ...car }
console.log(car2);
//新车子,跟car的长度不同,其他相同
var car3={ ...car,length:"4米" }
console.log(car3);
Set、Map、WeakSet、WeakMap
Set
ES6 提供了新的数据结构 Set。它类似于数组,但是成员的值都是唯一的,没有重复的值。
数组去重
[...new Set(array)]
字符串去重
[...new Set('ababbc')].join('')
Set 结构的实例有以下属性。
Set.prototype.constructor:构造函数,默认就是Set函数。
Set.prototype.size:返回Set实例的成员总数。
Set 实例的方法分为两大类:操作方法(用于操作数据)和遍历方法(用于遍历成员)。下面先介绍四个操作方法。
Set.prototype.add(value):添加某个值,返回 Set 结构本身。
Set.prototype.delete(value):删除某个值,返回一个布尔值,表示删除是否成功。
Set.prototype.has(value):返回一个布尔值,表示该值是否为Set的成员。
Set.prototype.clear():清除所有成员,没有返回值。
Set.prototype.constructor:构造函数,默认就是Set函数。
Set.prototype.size:返回Set实例的成员总数。
Set 实例的方法分为两大类:操作方法(用于操作数据)和遍历方法(用于遍历成员)。下面先介绍四个操作方法。
Set.prototype.add(value):添加某个值,返回 Set 结构本身。
Set.prototype.delete(value):删除某个值,返回一个布尔值,表示删除是否成功。
Set.prototype.has(value):返回一个布尔值,表示该值是否为Set的成员。
Set.prototype.clear():清除所有成员,没有返回值。
forEach
Map
ES6 提供了 Map 数据结构。它类似于对象,也是键值对的集合,但是“键”的范围不限于字符串,各种类型的值(包括对象)都可以当作键。也就是说,Object 结构提供了“字符串—值”的对应,Map 结构提供了“值—值”的对应,是一种更完善的 Hash 结构实现。如果你需要“键值对”的数据结构,Map 比 Object 更合适
const map = new Map([
['name', '张三'],
['title', 'Author']
]);
['name', '张三'],
['title', 'Author']
]);
const map = new Map();
map.set('foo', true);
map.size
map.get('foo');
map.has('foo');
map.delete('foo');
map.clear()
forEach
map.set('foo', true);
map.size
map.get('foo');
map.has('foo');
map.delete('foo');
map.clear()
forEach
WeakSet、WeakMap
成员只能是对象,而不能是其他类型的值。
WeakSet 中的对象都是弱引用,即垃圾回收机制不考虑 WeakSet 对该对象的引用
无forEach
函数拓展
特点
参数默认值
不定参数
箭头函数
https://www.runoob.com/w3cnote/es6-function.html
箭头函数不绑定arguments,取而代之用rest参数…解决
函数的this指向问题
箭头函数的this永远指向其上下文的 this,任何方法都改变不了其指向,如call(), bind(), apply()
箭头函数体内的this对象,就是定义时所在的对象,而不是使用时所在的对象
普通函数的this指向调用它的那个对象
不可以当作构造函数,也就是说,不可以使用new命令,否则会抛出一个错误。
// 回调函数
var Person = {
'age': 18,
'sayHello': function () {
setTimeout(function () {
console.log(this.age);
});
}
};
var age = 20;
Person.sayHello(); // 20
var Person1 = {
'age': 18,
'sayHello': function () {
setTimeout(()=>{
console.log(this.age);
});
}
};
var age = 20;
Person1.sayHello(); // 18
var Person = {
'age': 18,
'sayHello': function () {
setTimeout(function () {
console.log(this.age);
});
}
};
var age = 20;
Person.sayHello(); // 20
var Person1 = {
'age': 18,
'sayHello': function () {
setTimeout(()=>{
console.log(this.age);
});
}
};
var age = 20;
Person1.sayHello(); // 18
class
class Person{
// 构造器
constructor(name='default',age=0){
this.name = name;
this.age = age;
}
showName(){
return this.name;
}
showAge(){
return this.age;
}
}
// 构造器
constructor(name='default',age=0){
this.name = name;
this.age = age;
}
showName(){
return this.name;
}
showAge(){
return this.age;
}
}
class B {}
let b = new B();
b.constructor === B.prototype.constructor
let b = new B();
b.constructor === B.prototype.constructor
Point.prototype.constructor === Point
extends
class Person{
// 构造器
constructor(name,age){
this.name = name;
this.age = age;
}
showName(){
return this.name;
}
showAge(){
return this.age;
}
}
class Worker extends Person{
constructor(name,age,job='啦啦啦'){
// 继承超父类的属性
super(name,age);
this.job = job;
}
showJob(){
return this.job;
}
}
// 构造器
constructor(name,age){
this.name = name;
this.age = age;
}
showName(){
return this.name;
}
showAge(){
return this.age;
}
}
class Worker extends Person{
constructor(name,age,job='啦啦啦'){
// 继承超父类的属性
super(name,age);
this.job = job;
}
showJob(){
return this.job;
}
}
模块化
import 导入模块、export 导出模块
https://www.cnblogs.com/kreo/p/11069640.html
Promise、async\await
源码实现
Promise.all
Promise.race
Generator、yield
生成器( generator)是能返回一个迭代器的函数
算法
vue系类
jest单测
初始化
// 从测试实用工具集中导入 `mount()` 方法
// 同时导入你要测试的组件
import { mount } from '@vue/test-utils'
import Counter from './counter'
// 现在挂载组件,你便得到了这个包裹器
const wrapper = mount(Counter)
// 你可以通过 `wrapper.vm` 访问实际的 Vue 实例
const vm = wrapper.vm
// 同时导入你要测试的组件
import { mount } from '@vue/test-utils'
import Counter from './counter'
// 现在挂载组件,你便得到了这个包裹器
const wrapper = mount(Counter)
// 你可以通过 `wrapper.vm` 访问实际的 Vue 实例
const vm = wrapper.vm
dom获取
wrapper.html()
wrapper.contains('button')
wrapper.find('button')
wrapper.props()
import ParentComponent from '@/components/ParentComponent'
import ChildComponent from '@/components/ChildComponent'
const wrapper = mount(ParentComponent)
wrapper.find(ChildComponent)
wrapper.find(ChildComponent).vm.$emit('custom')
import ChildComponent from '@/components/ChildComponent'
const wrapper = mount(ParentComponent)
wrapper.find(ChildComponent)
wrapper.find(ChildComponent).vm.$emit('custom')
事件触发
emit
wrapper.vm.$emit('foo', 123)
// 断言事件的有效数据
expect(wrapper.emitted().foo[1]).toEqual([123])
// 断言事件的有效数据
expect(wrapper.emitted().foo[1]).toEqual([123])
tigger
const wrapper = mount(Component)
await wrapper.trigger('click')
wrapper.text().toContain('some different text')
await wrapper.trigger('click')
wrapper.text().toContain('some different text')
赋值
wrapper.setData({ count: 10 })
wrapper.setProps({ foo: 'bar' })
wrapper.setProps({ foo: 'bar' })
注意
任何导致操作 DOM 的改变都应该在断言之前 await nextTick 函数
await wrapper.vm.$nextTick()
await 语句来等待 flushPromises 刷新 Promise 的状态
await flushPromises()
jest.fn
Apis.getCustomerDetailInformation = jest.fn(() => {
return { code: 200, success: true, data: data }
})
return { code: 200, success: true, data: data }
})
jest.spyOn
cacheTimeSpy = jest.spyOn(vm, 'cacheTime')
expect(cacheTimeSpy).toHaveBeenCalled()
expect(cacheTimeSpy).toHaveBeenCalledTimes(1)
expect(cacheTimeSpy).toHaveBeenCalled()
expect(cacheTimeSpy).toHaveBeenCalledTimes(1)
断言
https://www.jianshu.com/p/c1b5676c1edd
toBe
使用 Object.is 来测试是否完全相等
not
用来测试相反的用例
toEqual
检查某个对象的值
toHaveLength
判断一个有长度的对象的长度
toContain
判断数组是否包含特定子项
toContainEqual
判断数组中是否包含一个特定对象
toHaveProperty(keyPath, value)
判断在指定的 path 下是否有这个属性,嵌套的 path 可以用 '.'分割
expect(houseForSale).toHaveProperty('bedrooms', 4)
expect(houseForSale).toHaveProperty('kitchen.area', 20);
toHaveBeenCalled
用来判断一个函数是否被调用过
toHaveBeenCalledTimes
判断函数被调用过几次
router
路由权限控制
https://zhuanlan.zhihu.com/p/55262808
mock
Vue
watch
基础用法
watch: {
obj: {
handler(newName, oldName) {
console.log('obj.a changed');
},
immediate: true, // 相当于立即执行
deep: true // 开启深层次的监听
}
}
obj: {
handler(newName, oldName) {
console.log('obj.a changed');
},
immediate: true, // 相当于立即执行
deep: true // 开启深层次的监听
}
}
特别用法
watch: {
'obj.a': {
handler(newName, oldName) {
console.log('obj.a changed');
},
immediate: true,
// deep: true
}
}
'obj.a': {
handler(newName, oldName) {
console.log('obj.a changed');
},
immediate: true,
// deep: true
}
}
immediate
true
代表如果在 wacth 里声明了 firstName 之后,就会立即先去执行里面的handler方法
false
就跟我们以前的效果一样,不会在绑定的时候就执行。
deep
true
深入观察,监听器会一层层的往下遍历,给对象的所有属性都加上这个监听器,但是这样性能开销就会非常大了,任何修改obj里面任何一个属性都会触发这个监听器里的 handler
false
就跟我们以前的效果一样
注销
// app为new出来的vue对象
const unWatch = app.$watch('text', (newVal, oldVal) => {
console.log(`${newVal} : ${oldVal}`);
})
unWatch(); // 手动注销watch
const unWatch = app.$watch('text', (newVal, oldVal) => {
console.log(`${newVal} : ${oldVal}`);
})
unWatch(); // 手动注销watch
filter
全局写法
Vue.filter('testfilter', function (value,text) {
// 返回处理后的值
return value+text
})
// 返回处理后的值
return value+text
})
组件中挂载
filters: {
changemsg:(val,text)=>{
return val + text
}
},
changemsg:(val,text)=>{
return val + text
}
},
使用场景
只能使用在{{}}和:v-bind
<h3 :title="test|changemsg(1234)">{{test|changemsg(4567)}}</h3>
{{ message | filterA('arg1', arg2) }}
filterA 被定义为接收三个参数的过滤器函数。参数依次为message、arg1、arg2
use
用法
插件是一个对象,必须提供 install 方法
插件是一个函数,它会被作为 install 方法
install 方法调用时,会将 Vue 作为参数传入。
实例
index.js
// 引入组件
import LoadingComponent from './loading.vue'
// 定义 Loading 对象
const Loading={
// install 是默认的方法。当外界在 use 这个组件的时候,就会调用本身的 install 方法,同时传一个 Vue 这个类的参数。
install:function(Vue){
Vue.component('Loading',LoadingComponent)
}
}
// 导出
export default Loading
import LoadingComponent from './loading.vue'
// 定义 Loading 对象
const Loading={
// install 是默认的方法。当外界在 use 这个组件的时候,就会调用本身的 install 方法,同时传一个 Vue 这个类的参数。
install:function(Vue){
Vue.component('Loading',LoadingComponent)
}
}
// 导出
export default Loading
main.js
import Loading from './components/loading/index'
Vue.use(Loading)
Vue.use(Loading)
App.vue
<template>
<div id="app">
<h1>vue-loading</h1>
<Loading></Loading>
</div>
</template>
<div id="app">
<h1>vue-loading</h1>
<Loading></Loading>
</div>
</template>
用 axios时,之所以不需要用 Vue.use(axios),就能直接使用,是因为开发者在封装 axios 时,没有写 install 这一步。至于为啥没写,那就不得而知了
directives
例子
https://blog.csdn.net/qq_31837621/article/details/80819126
https://www.jianshu.com/p/8d3980334b80
https://www.jianshu.com/p/6a4811eb0efe
https://blog.csdn.net/yin4302008/article/details/86727811
https://www.cnblogs.com/chenwenhao/p/11924161.html
全局注册
// 注册一个全局自定义指令 `v-focus`
Vue.directive('focus', {
// 当被绑定的元素插入到 DOM 中时……
inserted: function (el) {
// 聚焦元素
el.focus()
}
})
Vue.directive('focus', {
// 当被绑定的元素插入到 DOM 中时……
inserted: function (el) {
// 聚焦元素
el.focus()
}
})
组件内注册
directives: {
focus: {
// 指令的定义
inserted: function (el) {
el.focus()
}
}
}
focus: {
// 指令的定义
inserted: function (el) {
el.focus()
}
}
}
函数简写
Vue.directive('color-swatch', function (el, binding) {
el.style.backgroundColor = binding.value
})
el.style.backgroundColor = binding.value
})
在 bind 和 update 时触发相同行为,而不关心其它的钩子
钩子函数
bind
只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置
inserted
被绑定元素插入父节点时调用 (仅保证父节点存在,但不一定已被插入文档中)。
update
所在组件的 VNode 更新时调用,但是可能发生在其子 VNode 更新之前。指令的值可能发生了改变,也可能没有。但是你可以通过比较更新前后的值来忽略不必要的模板更新 (详细的钩子函数参数见下)。
componentUpdated
指令所在组件的 VNode 及其子 VNode 全部更新后调用。
unbind
只调用一次,指令与元素解绑时调用。
钩子函数参数
el
指令所绑定的元素,可以用来直接操作 DOM
binding
一个对象,包含以下 property
property
name
指令名,不包括 v- 前缀
value
指令的绑定值,例如:v-my-directive="1 + 1" 中,绑定值为 2
oldValue
指令绑定的前一个值,仅在 update 和 componentUpdated 钩子中可用。无论值是否改变都可用
expression
字符串形式的指令表达式。例如 v-my-directive="1 + 1" 中,表达式为 "1 + 1"
arg
传给指令的参数,可选。例如 v-my-directive:foo 中,参数为 "foo"
modifiers
一个包含修饰符的对象。例如:v-my-directive.foo.bar 中,修饰符对象为 { foo: true, bar: true }
vnode
Vue 编译生成的虚拟节点
oldVnode
上一个虚拟节点,仅在 update 和 componentUpdated 钩子中可用
mixins
经典文章
加载更多
https://zhuanlan.zhihu.com/p/59939294
局部混入
var mixin = {
data: function () {
return {
message: 'hello',
foo: 'abc'
}
}
}
new Vue({
mixins: [mixin],
data: function () {
return {
message: 'goodbye',
bar: 'def'
}
},
created: function () {
console.log(this.$data)
}
})
data: function () {
return {
message: 'hello',
foo: 'abc'
}
}
}
new Vue({
mixins: [mixin],
data: function () {
return {
message: 'goodbye',
bar: 'def'
}
},
created: function () {
console.log(this.$data)
}
})
全局混入
// 为自定义的选项 'myOption' 注入一个处理器。
Vue.mixin({
created: function () {
var myOption = this.$options.myOption
if (myOption) {
console.log(myOption)
}
}
})
Vue.mixin({
created: function () {
var myOption = this.$options.myOption
if (myOption) {
console.log(myOption)
}
}
})
规则
当组件和混入对象含有同名选项时,这些选项将以恰当的方式进行“合并”。
比如,数据对象在内部会进行递归合并,并在发生冲突时以组件数据优先。
比如,数据对象在内部会进行递归合并,并在发生冲突时以组件数据优先。
执行规则
data选项在混入时,数据对象在内部会进行递归合并,当发生冲突时,以组件数据优先
同名钩子函数混合为一个数组,两个钩子函数内部的逻辑都会被执行,且混入的比组件的先调用
为对象的选项如methods, components, directives将被 混合为同一个对象。冲突取组件键值对
自定义的混入策略
组件间通信
6种方式
vuex
$emit/$on
props/$emit
provide/inject
$attrs/$listeners
$parent/$child/$ref
参考文章
英文
axios、handler、immediate、deep、plugins、format、mixins
基础
渐进式框架
主张最少
Vue渐进式-先使用Vue的核心库,再根据你的需要的功能再去逐渐增加加相应的插件。
两个核心
数据驱动
在vue中,数据的改变会驱动视图的自动更新。传统的做法是需要手动改变DOM来使得视图更新,而vue只需要改变数据。
组件系统
组件化开发,优点很多,可以很好的降低数据之间的耦合度。将常用的代码封装成组件之后(vue组件封装方法),就能高度的复用,提高代码的可重用性。一个页面/模块可以由多个组件所组成。
vue生命周期钩子函数
创建前/后,载入前/后,更新前/后,销毁前/后
加载渲染过程
父beforeCreate->父created->父beforeMount->子beforeCreate->子created->子beforeMount->子mounted->父mounted
子组件更新过程
父beforeUpdate->子beforeUpdate->子updated->父updated
父组件更新过程
父beforeUpdate->父updated
销毁过程
父beforeDestroy->子beforeDestroy->子destroyed->父destroyed
https://www.cnblogs.com/yuliangbin/p/9348156.html
双向绑定的原理
https://www.cnblogs.com/sweeeper/p/10829887.html
https://www.jianshu.com/p/e7ebb1500613
监听器Observer
用来劫持并监听所有属性,如果有变动的,就通知订阅者
具体实现
Object.defineProperty( )
如果要对所有属性都进行监听的话,那么可以通过递归方法遍历所有属性值
订阅者Watcher
可以收到属性的变化通知并执行相应的函数,从而更新视图
解析器Compile
可以扫描和解析每个节点的相关指令,并根据初始化模板数据以及初始化相应的订阅器。
流程图
面试
vue面试题
大厂面试题
https://www.processon.com/view/5ee6689ef346fb1ae561f92d?fromnew=1#map
https://www.processon.com/view/5e6a3d4ce4b09b0f79e63647?fromnew=1#map
其它方法
debounce
高级组件
linux
命令行
https://www.cnblogs.com/yuncong/p/10247583.html
cd
change directory
ls
list
pwd
print working directory
mkdir
make directory
rmdir
remove directory
rm
remove
mv
move
cp
copy
cat
catenate
nginx
上传文件
https://www.cnblogs.com/nbf-156cwl/p/8641165.html
webpack
文章
webpack系统配置
文档
概念
webpack 是一个现代 JavaScript 应用程序的静态模块打包器(module bundler)。当 webpack 处理应用程序时,它会递归地构建一个依赖关系图(dependency graph),其中包含应用程序需要的每个模块,然后将所有这些模块打包成一个或多个 bundle
入口(entry)
entry 对象是用于 webpack 查找启动并构建 bundle
参数
对象
最完整的entry配置,其他形式只是它的简化形式而已,可拓展性高
数组
entry: ['./app.js', 'lodash']
=
entry: {
main: ['./app.js', 'lodash']
}
=
entry: {
main: ['./app.js', 'lodash']
}
字符串
entry: './app.js'
=
entry: {
main: './app.js'
}
=
entry: {
main: './app.js'
}
输出(output)
可以控制 webpack 如何向硬盘写入编译文件
参数
单入口起点
output: {
filename: 'bundle.js',
path: '/home/proj/public/assets'
}
filename: 'bundle.js',
path: '/home/proj/public/assets'
}
多入口起点
{
entry: {
app: './src/app.js',
search: './src/search.js'
},
output: {
filename: '[name].js',
path: __dirname + '/dist'
}
}
// 写入到硬盘:./dist/app.js, ./dist/search.js
entry: {
app: './src/app.js',
search: './src/search.js'
},
output: {
filename: '[name].js',
path: __dirname + '/dist'
}
}
// 写入到硬盘:./dist/app.js, ./dist/search.js
高级进阶
output: {
path: "/home/proj/cdn/assets/[hash]",
publicPath: "http://cdn.example.com/assets/[hash]/"
}
path: "/home/proj/cdn/assets/[hash]",
publicPath: "http://cdn.example.com/assets/[hash]/"
}
模板
[hash]
模块标识符(module identifier)的 hash
[chunkhash]
chunk 内容的 hash
[name]
模块名称
[id]
模块标识符(module identifier)
[query]
模块的 query,例如,文件名 ? 后面的字符串
loader
用于对模块的源代码进行转换。loader 可以使你在 import 或"加载"模块时预处理文件。
loader 用于对模块的源代码进行转换
module: {
rules: [
{
test: /\.css$/,
use: [
{ loader: 'style-loader' },
{
loader: 'css-loader',
options: {
modules: true
}
}
]
}
]
}
rules: [
{
test: /\.css$/,
use: [
{ loader: 'style-loader' },
{
loader: 'css-loader',
options: {
modules: true
}
}
]
}
]
}
插件(plugins)
是用来拓展webpack功能的,它们会在整个构建过程中生效,执行相关的任务
webpack.config.js
常用
官网插件链接
copyWebpackPlugin
打包拷贝静态文件
HtmlWebpackPlugin
简化了HTML文件的创建,以便为你的webpack包提供服务
ExtractTextWebpackPlugin
会将所有的入口 chunk(entry chunks)中引用的 *.css,移动到独立分离的 CSS 文件
OptimizeCssAssetsPlugin
用于优化或者压缩CSS资源
UglifyJsPlugin
对js文件进行压缩
CommonsChunkPlugin
当多个 bundle 共享一些相同的依赖,CommonsChunkPlugin 有助于提取这些依赖到共享的 bundle 中,来避免重复打包
Vue3
ref、reactive、toRef、toRefs
收藏
0 条评论
下一页