视频p78-
浏览器本地存储 webStorage
JSON.stringify ( JavaScript 对象或值 ) 方法 将一个 JavaScript 对象或值转换为 JSON 字符串
JSON.parse ( JSON 字符串 ) 方法 将数据转换为 JavaScript 对象。
本节笔记
- 存储内容大小一般支持5MB左右(不同浏览器可能还不一样)
- 浏览器端通过 Window.sessionStorage 和 Window.localStorage 属性来实现本地存储机制。
- 相关API:
xxxxxStorage.setItem('key', 'value');
该方法接受一个键和值作为参数,会把键值对添加到存储中,如果键名存在,则更新其对应的值。xxxxxStorage.getItem('person');
该方法接受一个键名作为参数,返回键名对应的值。xxxxxStorage.removeItem('key');
该方法接受一个键名作为参数,并把该键名从存储中删除。xxxxxStorage.clear()
该方法会清空存储中的所有数据。
备注:
一种组件间通信的方式,适用于:子组件 ===> 父组件
- 使用场景:A是父组件,B是子组件,B想给A传数据,那么就要在A中给B绑定自定义事件(事件的回调在A中)。
绑定自定义事件:(在父组件中)
- 第一种方式,在父组件中:
<Demo @atguigu="test"/>
或<Demo v-on:atguigu="test"/>
第二种方式,在父组件中:
<Demo ref="demo"/> ...... mounted(){ this.$refs.xxx.$on('atguigu',this.test) }
若想让自定义事件只能触发一次,可以使用
once
修饰符,或$once
方法。
- 第一种方式,在父组件中:
- 触发自定义事件:
this.$emit('atguigu',数据)
- 解绑自定义事件
this.$off('atguigu')
- 组件上也可以绑定原生DOM事件,需要使用
native
修饰符。 - 注意:通过
this.$refs.xxx.$on('atguigu',回调)
绑定自定义事件时,回调要么配置在methods中,要么用箭头函数,否则this指向会出问题! (回调函数谁调用,谁是this) 自定义事件传数据:父组件,定事件,写回调;子组件,触事件,传数据
全局事件总线 组件间通信
实现的设计思路
X就等于集中管理自定义事件的绑定和触发,通信的两个组件只需要在x里面找自定义事件就行了
反正每个组件在生成的时候都把自己的联系方式给 xx 的设计路线
demo:兄弟组件,student.vue 传数据到school.vue
弹幕笔记记录
“接受方在总线上绑定事件与回调函数,发送方触发总线上的事件与传参。”
“我悟了:所有的事件都统一绑定在X身上,而对应的回调都放在各个组件中。于是从X射出来的事件能触发任意组件中的回调。”
“x 就是一个共同的vc,可以触发同一个$emit”推理 改进 版本
全局事件总线总结
一种组件间通信的方式,适用于任意组件间通信。
安装全局事件总线:
new Vue({ ...... beforeCreate() { Vue.prototype.$bus = this //安装全局事件总线,$bus就是当前应用的vm }, ...... })
使用事件总线:
接收数据:A组件想接收数据,则在A组件中给$bus绑定自定义事件,事件的回调留在A组件自身。
methods(){ demo(data){......} } ...... mounted() { this.$bus.$on('xxxx',this.demo) }
提供数据:
this.$bus.$emit('xxxx',数据)
最好在beforeDestroy钩子中,用$off去解绑当前组件所用到的事件。
todolist 的组件通信改成事件总线写法
“父给子传用props,子给父传用自定义事件,跨组件传用全局事件总线。”
“全局事件总线的本质是给组件绑定自定义事件。 只不过这里的组件是this.$bus也就是Vue实例。”消息订阅与发布 组件间通信
一种组件间通信的方式,适用于任意组件间通信。
使用步骤:
- 安装pubsub:
npm i pubsub-js
- 引入:
import pubsub from 'pubsub-js'
接收数据:A组件想接收数据,则在A组件中订阅消息,订阅的回调留在A组件自身。
methods(){ demo(data){......} } ...... mounted() { this.pid = pubsub.subscribe('xxx',this.demo) //订阅消息 }
提供数据:
pubsub.publish('xxx',数据)
// 在数据提供方- 最好在beforeDestroy钩子中,用
PubSub.unsubscribe(pid)
去取消订阅。
- 安装pubsub:
todolist 改成消息订阅与发布模式
todolist 案例 - 编辑功能
。。。。这个没听懂
nextTick
- 语法:
this.$nextTick(回调函数)
- 作用:在下一次 DOM 更新结束后执行其指定的回调。
什么时候用:当改变数据后,要基于更新后的新DOM进行某些操作时,要在nextTick所指定的回调函数中执行。
过度与动画
引入动画库
Animate.css | A cross-browser library of CSS animations.
https://animate.style/
安装: npm install animate.css
引入:import”animate.css”;总结
作用:在插入、更新或移除 DOM元素时,在合适的时候给元素添加样式类名。
写法:
- 准备好样式:
- 元素进入的样式:
- v-enter:进入的起点
- v-enter-active:进入过程中
- v-enter-to:进入的终点
- 元素离开的样式:
- v-leave:离开的起点
- v-leave-active:离开过程中
- v-leave-to:离开的终点
- 元素进入的样式:
使用
<transition>
包裹要过度的元素,并配置name属性:<transition name="hello"> <h1 v-show="isShow">你好啊!</h1> </transition>
备注:若有多个元素需要过度,则需要使用:
<transition-group>
,且每个元素都要指定key
值。补课:Promise,axios
promise
学习资料来源
编程前端开发学习笔记/Promise学习笔记 · 努力学习的汪/洪学习笔记 - 码云 - 开源中国
[https://gitee.com/hongjilin/hongs-study-notes/tree/master/%E7%BC%96%E7%A8%8B%E5%89%8D%E7%AB%AF%E5%BC%80%E5%8F%91%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/Promise%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0](https://gitee.com/hongjilin/hongs-study-notes/tree/master/%E7%BC%96%E7%A8%8B_%E5%89%8D%E7%AB%AF%E5%BC%80%E5%8F%91%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/Promise%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0)
【小知识】第8期 js中Promise与async/await的用法简介_哔哩哔哩_bilibili
https://www.bilibili.com/video/BV12E411975X/?spm_id_from=333.788.recommend_more_video.1JavaScript两种异步方式(单线程编程语言):
- 准备好样式:
- 传统回调函数 (Callback Function) 例如 setTimeOut
回调函数缺点: 函数回调地狱 : 一个函数执行完在执行内部另外一个,一层一层嵌套
- Promise
需求
通过AJAX请求id ,再根据id请求用户名.再根据用户名,再根据用户名获取email
回调地狱
Promise 概念
Promise是异步编程的一种解决方案,比传统的解决方案——回调函数和事件——更合理和更强大。所谓Promise,简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果。<br />通俗讲,Promise是一个许诺、承诺,是对未来事情的承诺,承诺不一定能完成,但是无论是否能完成都会有一个结果。
Promise 的基本使用
语法
new Promise(( reslove, reject ) =>{})
- Promise接受一个函数作为参数
- 在参数函数中有两个参数
- resolve: 成功函数
- reject: 失败函数
Promise实例
promise实例有两个属性
- state: 状态
- result: 结果
1) Promise的状态
第一种状态: pending(准备,待解决,进行中)
第二种状态: fulfilled(已完成,成功)
第三种状态: rejected(已拒绝,失败)2) Promise状态的改变
示例1
const p = new Promise((resolve, reject) => {
//resolve(): 调用函数, 使当前Promise对象的状态改成fulfilled
reslove();
})
console.dir(p) // fulfilled
示例2
const p = new Promise((resolve, reject) => {
//resolve(): 调用函数, 使当前Promise对象的状态改成fulfilled
//reject(): 调用函数, 使当前Promise对象的状态改成rejected
//reslove();
reject()
})
console.dir(p)
- resolve(): 调用函数, 使当前Promise对象的状态改成fulFilled
- reject(): 调用函数,使当前Promise对象状态改成rejected
Promise状态的改变是一次性的
3) Promise 的结果
示例
const p = new Promise((resolve, reject) => {
//通过调用reslove,传递参数,改变 当前Promise对象的结果
resolve("成功的结果");
//reslove();
//reject("失败的结果")
})
console.dir(p)
Promise的方法
1) then方法
示例1
const p = new Promise((resolve, reject) => {
//通过调用reslove,传递参数,改变 当前Promise对象的结果
//reslove("成功的结果");
reject("失败的结果")
})
//then方法函数
//参数
//两个参数都是函数
//返回值: 是一个Promise对象
p.then(()=>{
//当Promise的状态使fulfilled时执行
console.log("成功的回调")
},()=>{
// 当Promise的状态时rejected时, 执行
console.log("失败时调用")
})
console.dir(p)
实例2
const p = new Promise((resolve, reject) => {
//通过调用reslove,传递参数,改变 当前Promise对象的结果
//reslove(123);
reject("失败的结果")
})
//then方法函数
//参数
//两个参数都是函数
//返回值: 是一个Promise对象
p.then((value)=>{
//当Promise的状态使fulfilled时执行
console.log("成功的回调",value)
},(err)=>{
// 当Promise的状态时rejected时, 执行
console.log("失败时调用",err)
})
console.dir(p)
- 在then方法的参数函数中,通过形参使用Promise对象的结果
then方法返回一个新的Promise实例,状态时pending
const p = new Promise((resolve, reject) => {
//通过调用reslove,传递参数,改变 当前Promise对象的结果
//reslove(123);
reject("失败的结果")
})
//then方法函数
//参数
//两个参数都是函数
//返回值: 是一个Promise对象
p.then((value)=>{
//当Promise的状态使fulfilled时执行
console.log("成功的回调",value)
},(err)=>{
// 当Promise的状态时rejected时, 执行
console.log("失败时调用",err)
})
console.dir(p)
Promise的状态不改变,不会执行then里的方法
//如果Promise的状态改变,then里的方法不会执行
const p = new Promise((resolve, reject) => {
}).then.((value) => {
console.log("成功")
},(reason) => {
console.log("失败")
})
在then方法中,通过return将返回的Promise实例改为fulfilled状态
//如果Promise的状态改变,then里的方法不会执行
const p = new Promise((resolve, reject) => {
})
const t = p.then((value) => {
console.log("成功")
//使用return可以将t实例的状态改为fulfilled
return 123
},(reason) => {
console.log("失败")
})
t.then.((value) => {
console.log("成功2",value)
},(reason) => {
console.log("失败2")
})
在then方法中,出现代码错误,将返回的Promise实例改为rejected状态
//如果Promise的状态改变,then里的方法不会执行
const p = new Promise((resolve, reject) => {
})
const t = p.then.((value) => {
console.log("成功")
//使用return可以将t实例的状态改为fulfilled
return 123
},(reason) => {
//如果这里代码出错,会将t实例的状态改为rejected
console.log("失败")
})
t.then.((value) => {
console.log("成功2",value)
},(reason) => {
console.log("失败2")
})
2) catch方法
示例
const p = new Promise((resolve, reject) => {
//reject()
//console.log(a)
throw new Error("出错了");
})
//思考: catch中的参数函数在什么时候被执行
//1. 当Promise的状态改为rejcted.被执行
//2. 当Promise执行过程出现代码错误时,被执行
p.catch((reason => {
console.log("失败", reason)
})
console.log(p);
优化代码
示例
//封装ajax请求
function getData(url, data = {}){
return new Promise((resolve, reject) => {
$.ajax({
//发送请求类型
type: "GET",
url: url,
data: data,
success: function (res) {
// 修改Promise状态为成功, 修改Promise的结果res
resolve(res)
},
error:function (res) {
// 修改Promise的状态为失败,修改Promise的结果res
reject(res)
}
})
}
}
//调用函数
getData("data1.json")
.then((data) => {
//console.log(data)
const { id } = data
return getData("data2.json", {id})
})
.then((data) => {
//console.log(data)
const { usename } = data
return getData("data3.json", {usename})
})
.then((data) => {
console.log(data)
})
Promise的实际应用
加载图片
我们可以将图片的加载写成一个Promise,一旦加载完成,Promise的状态就发生变化
const preloadImage = function (path) {
return new Promise(function (resolve, reject) {
const image = new Image();
image.onload = resolve;
image.onerror = reject;
image.src = path;
});
};
ECMA17 的 async/ await
一句话概括:
语法糖,让异步操作变简单的,这两关键字基本同根同生,被 async 修饰的 funcation 接受请求必须用 await
1) async 函数
- 函数的返回值为 promise 对象
- promise 对象的结果由 async 函数执行的返回值决定
示例
async function main(){
//1.如果返回值是一个非Promise类型的数据
// return 一个字符串 数字 布尔值等都是成功的Promise对象
//2. 如果返回的时一个Promise对象
// return new Promise((resolve, reject) => {
//resolve("OK") 返回的是成功Promise对象,状态值:[[PromiseState]]:"fulfilled"
//reject("Err") 返回的是失败Promise对象,状态值:[[PromiseState]]:"rejected"
//3. 抛出异常
throw "oh No" //状态值:[[PromiseState]]:"rejected",结果是抛出的值
})
}
let result = main();
console.log(result);
返回值是一个Promise对象
2) await 表达式
await 右侧的表达式一般为 promise 对象, 但也可以是其它的值
2. 如果表达式是 promise 对象, await 返回的是 promise 成功的值
3. 如果表达式是其它值, 直接将此值作为 await 的返回值注意
await 必须写在 async 函数中, 但 async 函数中可以没有 await
2. 如果 await 的 promise 失败了, 就会抛出异常, 需要通过 try…catch 捕获处理3) async和await结合
示例
const fs = require("fs");
const util = require("util");
const mineReadFile = util.promisify(fs.readFile);//promisify转换为Promise形态的函数
async function main(){
//捕获处理
try{
//读取第一个文件的内容
let data1 = await mineReadFile("./resource/1.html");
let data2 = await mineReadFile("./resource/2.html");
let data3 = await mineReadFile("./resource/3.html");
}catch(e){
console.log(e):
}
}
Axios (ajax 请求库)
axios是一个基于Promise的HTTP客户端,可以用在浏览器和node.js中,向服务器发送AJAX请求进行数据交换,是现在前端最热门的请求工具。
学习资料来源
- 尚硅谷Web前端axios入门与源码解析_哔哩哔哩_bilibilihttps://www.bilibili.com/video/BV1wr4y1K7tq?p=2&spm_id_from=pageDriver
- 洪学习笔记: 这是@hongjilin的学习笔记 https://gitee.com/hongjilin/hongs-study-notes/tree/master/%E7%BC%96%E7%A8%8B_%E5%89%8D%E7%AB%AF%E5%BC%80%E5%8F%91%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/Ajax%E3%80%81Axios%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0
【axios】使用json-server 搭建REST API - 使用axios - 自定义axios - 取消请求 - 拦截器_YK菌的博客-CSDN博客 https://blog.csdn.net/weixin_44972008/article/details/114368528
json-server
自己起一个本地的mock-server来完全模拟请求以及请求回来的过程。用来快速搭建REST API 的工具包
使用json-server
- 下载: npm install -g json-server
- 目标根目录下创建数据库 json 文件: db.json
启动服务器执行命令: json-server —watch db.json
{ "posts": [ { "id": 1, "title": "json-server", "author": "typicode" }, { "id": 2, "title": "json-server2", "author": "typicode" } ], "comments": [ { "id": 1, "body": "some comment", "postId": 1 } ], "profile": { "name": "typicode" } }
使用浏览器访问测试
Axios的理解与使用
axios 是什么?
- 前端最流行的 ajax 请求库
- react/vue 官方都推荐使用 axios 发 ajax 请求
- 文档: https://github.com/axios/axios
引入:scriptsrc="https://cdn.bootcdn.net/ajax/libs/axios/0.21.1/axios.js"
安装:npm install axios
axios 特点
- 基于 xhr + promise 的异步 ajax 请求库
- 浏览器端/node 端都可以使用
- 支持请求/响应拦截器
- 支持请求取消
- 请求/响应数据转换
-
axios 常用语法
axios(config): 通用/最本质的发任意类型请求的方式
- axios(url[, config]): 可以只指定 url 发 get 请求
- axios.request(config): 等同于 axios(config)
- axios.get(url[, config]): 发 get 请求
- axios.delete(url[, config]): 发 delete 请求
- axios.post(url[, data, config]): 发 post 请求
- axios.put(url[, data, config]): 发 put 请求
- axios.defaults.xxx: 请求的默认全局配置
- axios.interceptors.request.use(): 添加请求拦截器
- axios.interceptors.response.use(): 添加响应拦截器
- axios.create([config]): 创建一个新的 axios(它没有下面的功能)
- axios.Cancel(): 用于创建取消请求的错误对象
- axios.CancelToken(): 用于创建取消请求的 token 对象
- axios.isCancel(): 是否是一个取消请求的错误
- axios.all(promises): 用于批量执行多个异步请求
axios.spread(): 用来指定接收所有成功数据的回调函数的方法
原理图
难点语法的理解和使用
vue脚手架配置代理(两种方式)
补完课 又回来了。。。如何用 vue-cli 解决 ajax 跨域问题
代理服务器解释
因为浏览器和服务器之间存在跨域问题,端口号必须一致。但是服务器与服务器之间没有跨域问题,所以通过代理服务器接收到主服务器中的数据,然后浏览器去访问代理服务器的数据。
这是为了解决浏览器不支持跨域请求,针对的是浏览器。方式一
xhr 的二次封装
在vue.config.js中添加如下配置:devServer:{ proxy:"http://localhost:5000" }
说明:
优点:配置简单,请求资源时直接发给前端(8080)即可。
- 缺点:不能配置多个代理,不能灵活的控制请求是否走代理。
工作方式:若按照上述配置代理,当请求了前端不存在的资源时,那么该请求会转发给服务器 (优先匹配前端资源)
方式二
编写 vue.config.js 配置具体代理规则:module.exports = { devServer: { proxy: { '/api1': {// 匹配所有以 '/api1'开头的请求路径 target: 'http://localhost:5000',// 代理目标的基础路径 changeOrigin: true, pathRewrite: {'^/api1': ''} // 这个重要!把/api1 换成空,确保转发到资源服务器的路径不带/api1 }, '/api2': {// 匹配所有以 '/api2'开头的请求路径 target: 'http://localhost:5001',// 代理目标的基础路径 changeOrigin: true, pathRewrite: {'^/api2': ''} } } } } /* changeOrigin设置为true时,服务器收到的请求头中的host为:localhost:5000 changeOrigin设置为false时,服务器收到的请求头中的host为:localhost:8080 changeOrigin默认值为true */
说明:
1. 优点:可以配置多个代理,且可以灵活的控制请求是否走代理。
2. 缺点:配置略微繁琐,请求资源时必须加前缀。插槽(父组件向子组件指定位置插入html结构)
作用:让父组件可以向子组件指定位置插入html结构,也是一种组件间通信的方式,适用于 父组件 ===> 子组件 。
- 分类:默认插槽、具名插槽、作用域插槽
使用方式:
默认插槽:
父组件中: <Category> <div>html结构1</div> </Category> 子组件中: <template> <div> <!-- 定义插槽 --> <slot>插槽默认内容...</slot> </div> </template>
具名插槽: slot由v-slot指令取代了,可以在具名和作用域插槽中使用
父组件中: <Category> <!-- <template slot="center"> <div>html结构1</div> </template> !--> <template v-slot:footer> <div>html结构2</div> </template> </Category> 子组件中: <template> <div> <!-- 定义插槽 --> <!-- <slot name="center">插槽默认内容...</slot> !--> <slot name="footer">插槽默认内容...</slot> </div> </template>
作用域插槽:
- 理解:数据在组件的自身,但根据数据生成的结构需要组件的使用者来决定。(games数据在Category组件中,但使用数据所遍历出来的结构由App组件决定)
- 具体编码:
```vue
父组件中:
- {{g}}
<template slot-scope="scopeData"> <!-- 生成的是h4标题 --> <h4 v-for="g in scopeData.games" :key="g">{{g}}</h4> </template>
子组件中:
export default { name:'Category', props:['title'], //数据在子组件自身 data() { return { games:['红色警戒','穿越火线','劲舞团','超级玛丽'] } }, }
```