在vue初始化的时候,会对data当中的每一个属性进行遍历,创建对应的setter和getters,并创建与这个key对应的dep,这个dep是一个数组,然后当对模板进行编译的时候,发现有使用到这个data当中的某一个属性的时候,就会创建一个watcher并添加到与data当中属性对应的dep当中
当数据发生变化的时候,observe监视到了,就会通知dep当的所有watcher,然后watcher触发更新
行内样式(内联样式): 直接写在标签上的属性
<标签名 style="属性1:属性值1;属性2:属性值2;">内容标签名>
**内部样式:**将css样式写在style
当中,比如下面代码
link
标签引入的
根据权重来计算出来的
*
的权重为1 , 标签选择器的权重为10,类选择器的权重为100,id选择器的权重为1000来进行计算的(权重值可能不一样,但是是这样子来算的),内联样式最高!import
会将至最高级!具体看mdnweb吧~这里只举例子
beforeCreate 创建前
created 创建后
beforeMount 挂载前
mounted 挂载后
beforeUpdate 更新前
updated 更新后
beforeDestroy 销毁前
destroyed 销毁后
需要重点关注的4个生命周期
beforeCreate
创建前
created
创建后
data
,methods
被绑定到了实例身上,但是依旧获取不到DOMbeforeMount
mounted
v-model原来写法
<input type="text" v-model="msg"/>
v-model拆解写法
<input type="text" :value="msg" @input="msg = $event.target.value"/>
父组件当中:
<template>
<div>
<One v-model="money"></One>
<div>父容器的money{{ money }}</div>
</div>
</template>
<script>
export default {
name: "",
data() {
return {
money: 1000,
};
},
};
</script>
子组件当中:
<template>
<div>
<input :value="value" @input="$emit('input',$event.target.value)" />
<div>儿子当中的值{{ value }}</div>
</div>
</template>
<script>
export default {
name: "One",
props:["value"]
};
</script>
//官方版
const UserDetails = {
template: `...`,
beforeRouteEnter(to, from) {
// 在渲染该组件的对应路由被验证前调用
// 不能获取组件实例 `this` !
// 因为当守卫执行时,组件实例还没被创建!
},
beforeRouteUpdate(to, from) {
// 在当前路由改变,但是该组件被复用时调用
// 举例来说,对于一个带有动态参数的路径 `/users/:id`,在 `/users/1` 和 `/users/2` 之间跳转的时候,
// 由于会渲染同样的 `UserDetails` 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。
// 因为在这种情况发生的时候,组件已经挂载好了,导航守卫可以访问组件实例 `this`
},
beforeRouteLeave(to, from) {
// 在导航离开渲染该组件的对应路由时调用
// 与 `beforeRouteUpdate` 一样,它可以访问组件实例 `this`
},
}
//注释版
beforeRouteEnter(to,from,next){
console.log("路由进入之前",to,from);
//手动调用next()方法,确保路由跳转继续执行
next();
}
beforeRouteUpdate(to,from,next){
console.log("路由更新之前",to,from);
next();
}
beforeRouteLevae(to,from,next){
console.log("路由离开之前",to,from);
next();
}
a:link {
color: #111
}
a:hover {
color: #222
}
div:first-child {
color: #333
}
div:nth-child(3) {
color: #444
}
等等
p::first-line {
color: #555
}
p::first-letter {
color: #666
}
a::after {
content: "helloWorld"
}
a::before {
content: "helloWorld"
}
代码:
<script>
//类似于axios({...})
const axios = (options) => {
//获取method 和 url
let {
method,
url
} = options;
if (method && url) {
var returnPromise = new Promise((resolve, reject) => {
let xhr = new XMLHttpRequest();
xhr.open(method, url);
xhr.send();
xhr.onreadystatechange = function () {
if (xhr.readyState == 4 && xhr.status >= 200 & xhr.status < 300) {
resolve(xhr.response);
}
};
//监听错误的
xhr.onerror = function () {
reject(new Error(xhr.statusText))
}
});
return returnPromise;
} else {
return Promise.reject("请输入完整的参数");
}
}
axios({
method: "get",
url: "https://api.oick.cn/dog/ap1i.php"
}).then(data => {
console.log(data);
});
</script>
基本原理都是利用边框
三角形:
@在线演示
关键是设置width为0
DOCTYPE html>
<head>
<style>
*{
margin: 0;
padding: 0;
}
#app{
width: 0;
border-top: 100px solid transparent;
border-bottom: 100px solid green;
border-left: 100px solid transparent;
border-right: 100px solid transparent;
}
style>
head>
<body>
<div id="app">div>
body>
html>
梯形:
@在线演示
关键是设置width和height的值
DOCTYPE html>
<head>
<style>
*{
margin: 0;
padding: 0;
}
#app{
width: 50px;
height: 50px;
border-top: 100px solid transparent;
border-bottom: 100px solid green;
border-left: 100px solid transparent;
border-right: 100px solid transparent;
}
style>
head>
<body>
<div id="app">div>
body>
html>
目的就是为了确认双方的接收能力和发送能力是否正常
客户端向服务端发送一个SYN(同步序列),等待服务器确认
服务端收到客户端的SYN后进行确认客户端的SYN包,然后也发送一个自己的SYN包,发送(SYN+ACK)包给客户端
客户端收到SYN+ACK包后,向服务端发送确认包ACK,发送完成则建立连接,开始传输数据
当客户端撤销相应的TCB后,才进入CLOSED状态
大概过程
简单来说一句话的博主
for…in是es5的用于遍历key
for…of是es6的用于遍历value
<script>
var arr = ["李白", "诗人", "陋室铭"];
for (var key in arr) {
//0 1 2
console.log(key);
}
for (var value of arr) {
//李白 诗人 陋室铭
console.log(value);
}
</script>
一个比较神奇的例子:
Object.prototype.objCustom = function () {};
Array.prototype.arrCustom = function () {};
let iterable = [3, 5, 7];
iterable.foo = "hello";
for (let i in iterable) {
console.log(i); // 0, 1, 2, "foo", "arrCustom", "objCustom"
}
//arrCustom是继承自Array的属性,objCustom是继承自Object的属性。
for (let i of iterable) {
console.log(i); // 3, 5, 7
}
正向代理:
面向客户,帮助客户解决问题,比如说我要访问YouTube,配置nginx后就可以访问了,这就是正向代理
反向代理:
面向服务器,帮助服务器解决问题,比如配置代理转发请求,原来是本地的请求转发到远程
弹性盒布局笔记
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Documenttitle>
<style>
*{
margin: 0;
padding: 0;
}
#wrap{
width: 306px;
height: 304px;
display: flex;
border: 1px solid red;
/* 关键是设置弹性盒是否换行,不然的话就会压缩 */
flex-wrap: wrap;
}
#wrap div{
width: 100px;
height: 100px;
border: 1px solid blue;
}
style>
head>
<body>
<div id="wrap">
<div id="one">div>
<div id="two">div>
<div id="three">div>
<div id="four">div>
<div id="five">div>
<div id="six">div>
<div id="seven">div>
<div id="eight">div>
<div id="nine">div>
div>
body>
html>
效果图
宏任务
:定时器
微任务
:promise
微任务的优先级大于宏任务
computed是带缓存的,只有当引用的数据发生变化的时候才会重新计算,而methods是每次调用都会重新执行
computed是响应式的,methods不是响应式的
computed可以具有getter和setter方法,因此可以赋值,而methods是不行的。
data(){
return {
name:"李",
lastName:"白"
}
},
computed:{
fullName(){
return this.name+this.lastName;
},
//等同于
fullName:{
get(){
return this.name+this.lastName
}
},
//写全点这样子写
fullName:{
get(){
return this.name+this.lastName;
},
set(newValue){
//处理newValue
}
}
}
<script>
function father(){
var a = 100;
var b = function(){
//内部函数有对上层作用域的引用
console.log(a);
a++;
}
return b;
}
// 内部函数在所在定义域外保持引用并进行访问
var temp = father();
temp();
temp();
temp();
</script>
prototype
,这个属性指向的是一个对象,我们叫这个对象叫原型对象__proto__
,这个属性指向其构造函数的prototype
属性,并且有如下关系(实例化对象.__proto__ === 构造函数.prototype
)sex
过程
sex
属性,如果有,就返回,没有就接着下一步寻找sex
属性(通过实例化对象.__proto__
来访问),有就返回,没有就下一步寻找实例化对象.__proto__.__proto__
来进行访问并寻找是否有sex
属性 <script>
function Dog(name, color) {
this.name = name;
this.color = color;
}
//为原型链上添加一个属性'sex';
Dog.prototype.sex = "未知";
//建立一个实例化对象
var xiaobai = new Dog("小白", "白色");
//输出结果为 '未知'
console.log(xiaobai.age);
</script>
hasOwnProperty
查找某一个对象自身是否有某一个属性,不会去查找他的原型链 <script>
function Dog(name, color) {
this.name = name;
this.color = color;
}
//为原型链上添加一个属性'sex';
Dog.prototype.sex = "未知";
//建立一个实例化对象
var xiaobai = new Dog("小白", "白色");
//搜索实例化对象身上是否有属性'sex'
var result = xiaobai.hasOwnProperty("sex");
//输出结果为false
console.log(result);
</script>
创建一个新的实例化对象
该构造函数的this指向新的实例化对象
执行该构造函数体
返回这个this(如果没有返回值的情况下)
创建一个新对象,并在内存当中开辟一个新对象
将新对象的__proto__
(隐式原型链)指向构造函数的prototype
(显示原型链)
将构造函数的this指向新的实例化对象
返回这个新对象
在router
配置文件中添加如下代码
const originalPush = VueRouter.prototype.push;
//解决重复提交相同链接报错
VueRouter.prototype.push = function push(location, onResolve, onReject) {
if (onResolve || onReject)
return originalPush.call(this, location, onResolve, onReject)
return originalPush.call(this, location).catch((err) => {
if (VueRouter.isNavigationFailure(err)) {
// resolve err
return err
}
// rethrow error
return Promise.reject(err)
})
}
const originalReplace = VueRouter.prototype.replace;
VueRouter.prototype.replace = function replace(location, onResolve, onReject) {
if (onResolve || onReject){
//回调函数里面会用到this的指向,所以就要使用call
return originalReplace.call(this, location, onResolve, onReject)
}
return originalReplace.call(this, location).catch((err) => {
if (VueRouter.isNavigationFailure(err)) {
//如果为相同链接引发的错误,返回错误原因,promise状态为resolve
// resolve err
return err
}
// rethrow error
return Promise.reject(err)
})
}
$nextTick
即可,保证数据有了后,dom被渲染了后在执行swiper初始化操作 watch:{
/* 监视bannerList数据更新 */
bannerList(){
/* 等待页面更新完成后执行回调 */
this.$nextTick(()=>{
//不应该使用类选择器的,这样子后期生成会选择所有相同的类!!
var mySwiper = new Swiper(this.$refs.mySwiper, {
// direction: 'vertical', // 垂直切换选项
loop: true, // 循环模式选项
// 如果需要分页器
pagination: {
el: ".swiper-pagination",
},
autoplay: {
//触碰后不会停止自动切换
disableOnInteraction: false,
},
// 如果需要前进后退按钮
navigation: {
nextEl: ".swiper-button-next",
prevEl: ".swiper-button-prev",
},
});
});
}
},
<script>
var tempArray = [1,2,3,4,5,5,6,7];
//转化为set
var tempSet = new Set(tempArray);
//set转换回来数组 - 方法1
var tempAfterArray1 = [...tempSet];
///set转换回来数组 - 方法2
var tempAfterArray2 = Array.from(tempSet);
//[1, 2, 3, 4, 5, 6, 7]
console.log(tempAfterArray1);
//[1, 2, 3, 4, 5, 6, 7]
console.log(tempAfterArray2);
</script>
for(var i = 0;i<tempArray.length;i++){
for(var j = i+1;j<tempArray.length;j++){
if(tempArray[i] == tempArray[j]){
tempArray.splice(j,1);
j--;
}
}
}
indexOf
在数组中,返回该数组中第一个找到的索引位置,若未找到,则返回-1var tempArray = [1, 2, 5, 5, 6, 6, 7];
//item为当前遍历的项
//index为当前遍历项的索引
var a = tempArray.filter((item, index) => {
return tempArray.indexOf(item) == index;
})
//[1, 2, 5, 6, 7]
console.log(a);
//遍历过程
item = 1,index=0
tempArray.indexOf(item) 返回 0
return 0 == 0 ;//为true,存储'1'
item = 2,index=1
tempArray.indexOf(item) 返回 1
return 1 == 1 ;//为true,存储'2'
item = 5,index=2
tempArray.indexOf(item) 返回 2
return 2 == 2 ;//为true,存储'5'
item = 5,index=3
tempArray.indexOf(item) 返回 2
return 2 == 3 ;//为false,不存储
item = 6,index=4
tempArray.indexOf(item) 返回 4
return 4 == 4 ;//为true,存储'6'
item = 6,index=5
tempArray.indexOf(item) 返回 4
return 4 == 5 ;//为false,不存储
item = 7,index=6
tempArray.indexOf(item) 返回 6
return 6 == 6 ;//为true,存储'7'
indexOf
let temp = [];
tempArray.forEach(item=>{
if(temp.indexOf(item)===-1){
temp.push(item);
}
})
特点:
数组的解构赋值
var str = "动感超人&18";
let[name,age] = str.split("&");
console.log(name,age);//动感超人 18
也可以跳过接收
var str = "动感超人&18";
let[,age] = str.split("&");
console.log(age);// 18
对象的解构赋值
var objName = {
name:"李白",
age:2000,
}
let {name,age}=objName;
console.log(name,age);//李白 2000
Promise.reject(reason)
方法返回一个带有拒绝原因的Promise
对象。Promise.resolve(value)
方法返回一个以给定值解析后的Promise
对象Promise.all(iterable)
方法获取这个可迭代对象的promise的结果,
reject
,那么就会触发catch
,返回的值就是这个reject
传递过来的值resolve
,那么就会触发then
,返回的值就是由resolve
传递过来的值组成的数组//iterable中有一个是reject
<script>
var p1 = Promise.resolve("promise1");
var p2 = Promise.reject("promise2");
var p3 = Promise.resolve("promise3");
Promise.all([p1, p2, p3]).then((data) => {
//不会被执行
console.log(data);
}).catch(function (error) {
//catch方法将会被执行,输出结果为:"promise2"
console.log(error);
});
</script>
//iterable均为resolve
<script>
var p1 = Promise.resolve("promise1");
var p2 = Promise.resolve("promise2");
var p3 = Promise.resolve("promise3");
Promise.all([p1, p2, p3]).then((data) => {
//输出['promise1', 'promise2', 'promise3']
console.log(data);
}).catch(function (error) {
//不会被执行
console.log(error);
});
</script>
Promise.race(iterable)
略
?.
为可选链操作符var a = {
b:{
c:{
d:{
name:"李白的师傅"
}
}
}
}
d
的数据,就要这样子,才不会发生报错var dataD = a && a.b && a.b.c && a.b.c.d && a.b.c.d.name
var dataD = a?.b?.c?.d?.name
resolve
或者reject
<script>
async function getResult(){
return Promise.resolve("解决了");
}
console.log(getResult());
</script>
<script>
async function getResult(){
return Promise.reject("失败了");
}
console.log(getResult());
</script>
resolve-输出一个状态为pending的promise
reject-输出一个状态为pending的promise 并引发报错提示
promise
对象<script>
async function getResult(){
return "看看我是什么"
}
console.log(getResult());
</script>
返回一个状态为fulfiled的promise
<script>
async function getResult(){
return new Error('出错啦')
}
console.log(getResult());
</script>
有时候在项目当中,经常使用await
来发送ajax请求获取数据后的操作,因为await可以阻塞进程,等待这个promise有结果后才开始后面的代码!!!
<script>
function testAwait() {
return new Promise((resolve, reject) => {
resolve("成功解决问题")
})
}
async function getResult() {
var result;
try {
result = await testAwait();
console.log("成功了,结果为-", result);
} catch (error) {
console.log("捕捉到失败,原因为-", error);
}
console.log("我可不可以执行到这里")
}
console.log(getResult());
</script>
例子1: 遇上失败的promise并且使用try...catch
捕捉
<script>
function testAwait() {
return new Promise((resolve, reject) => {
reject("失败了")
})
}
async function getResult() {
var result;
try {
result = await testAwait();
console.log("成功了,结果为",result);
} catch (error) {
console.log("捕捉到失败,原因为",error);
}
//输出结果证明可以
console.log("我可不可以执行到这里")
}
console.log(getResult());
</script>
例子1输出结果
例子2: 遇上失败的promise没有使用,没有使用try..catch捕捉
<script>
function testAwait() {
return new Promise((resolve, reject) => {
reject("失败了")
})
}
async function getResult() {
var result = await testAwait();;
console.log("获取到的结果为",result);
console.log("我可不可以执行到这里");//输出结果证明不会执行到这里
// try {
// result = await testAwait();
// console.log("成功了,结果为",result);
// } catch (error) {
// console.log("捕捉到失败,原因为",error);
// }
}
console.log(getResult());
</script>
例子2输出结果
会发现报错了,并且console.log("我可不可以执行到这里")
没有执行,因为promise失败导致程序中断!
reject
,后面代码就不会被执行了try...catch
来解决,并且catch
捕捉到的原因为reject
传递的参数值tab上面按键的符号 里面可以用${变量名}
来使用变量
`你的名字为${name},年龄为${age}`
执行上下文是指函数调用时在执行栈中产生的当前函数的执行环境,该环境如隔绝外部世界的容器边界,保管可访问的变量、this对象等。(说通俗点就是函数执行时候的一个环境)
window对象
我们却可以使用window对象
,并且却可以直接输出this
)不管是全局执行上下文,还是函数执行上下文,上下文的创建过程都是如下
使用这一段代码来作为全局执行上下文和函数执行上下文的例子
<script>
function Dog(name,age){
this.name = name;
this.age = age;
}
var xiaobai = new Dog("小白",10);
</script>
要执行的代码如下,注意注释
<script>
//函数定义,不执行
function Dog(name,age){
this.name = name;
this.age = age;
}
//执行
var xiaobai = new Dog("小白",10);
</script>
执行var xiaobai = new Dog("小白",10);
代码的过程 这里是在调用函数的过程,所以可以理解为在调用函数执行上下文,所以我们跳转到函数执行上下文的过程
function Dog(name,age){
//执行里面的代码
this.name = name;
this.age = age;
}
注意: 执行函数上下文完成,所属的栈会被丢弃!
但是,丢弃之前返回了this指向,并存储在了变量xiaobai
当中
function Dog(name,age){
//执行里面的代码,执行完成后销毁
this.name = name;
this.age = age;
//你不添加系统也会自动加一个
return this;
}
var xiaobai = new Dog("小白",10);
如图,销毁前返回了this并保存在了变量xiaobai
当中
getter
和setter
getter
和setter
的,通过数据劫持去添加了set,getsetter
和getter
(也就是数据劫持)loader
: 是文件加载器,可以加载资源文件,并对这些文件进行一些处理,比如:编译,压缩等,plugin
:webpack在运行的生命周期会广播出许多事件,plugin可以监听这些事件,在合适的时机中通过webpack提供的api改变输出结果区别:
常见的模块
css-loader
: 加载.css文件(也就是可以使用css模块了)style-loader
:使用
将css-loader内部样式注入到我们的HTML页面
bable-loader
:es6转化为es6(js语法转换)mini-css-extract-plugin
: 提取css为单独的文件postcss(完整的应该为postcss postcss-loader postcss-preset-env)
:处理css兼容性问题