自用 sgg

155 阅读5分钟

登录注册

注册:向服务器post账号和密码

登录:向服务器post账号和密码,后端进行匹配,成功则返回token存入本地的localstorage中

form表单验证

注册用的是element-ui的表单组件 配置验证validator

前后端认证方式

juejin.cn/post/684490…

目的:为了跟踪会话信息,标记访问者的身份。(http是无状态协议,会话结束后,不保存会话信息,每次打开新页面都要重新登录)

1.session cookie

2.token验证

令牌,访问资源接口(API)所需要的凭证

客户端post用户名和密码给服务端,服务端验证后返回一个token

客户端将token保存在本地如localstorage 然后写在请求头的authorization字段里

服务端验证token后返回相应资源。

token相比cookie来说 不受同源的限制 JWT (json web token)

JWT是token的一种 包括header payload和signature 中间用.隔开 header是元数据 payload 是实际数据 signature是对前两个的加密 三个JSON对象会使用 Base64URL 算法转成字符串

www.ruanyifeng.com/blog/2018/0…

自动刷新token

refresh token是用来请求新的token的

token的有效时间短,refresh token的有效时间长(7-14天)

1.后端返回一个refresh token和token 用户存储在本地

2.携带token发请求,如果http状态吗401(没有访问权限)说明token过期,携带fresh token发请求新的token

3.如果refresh token有效 返回新的token 如果refreshtoken也过期了 就重新登录 www.ay1.cc/article/302…

function refreshTokenRequst(){
  return axios.request({
    baseURL: BASE_URL,
    url:'/app/renewal',
    method: 'POST',
    data:{
    refreshToken:localStorage.getItem('refreshToken')
    },
  })
}

//响应拦截器
// 添加响应拦截器 
service.interceptors.response.use((response) => {
    NProgress.done()
    return response.data
}, (error) => {
    NProgress.done()
    //解析出状态码和请求配置
    const {config,status} = error
    if(status === 401){
        try{
            const refreshTokenResult = refreshTokenRequst()
            if(refreshTokenResult.data && refreshTokenResult.code === 200){
                //存入新的token
                localStorage.setItem('token',refreshTokenResult.data)
                //重新发请求 请求拦截器会带上新的token
                const newRes = service(config)
                return newRes.data
                }
            }catch(e){
                return Promise.reject(e)            
            }
        }
    }
    alert( `请求出错: ${error.message||'未知错误'}`)
    // 后面可以选择不处理或处理
    return Promise.reject(error)
})

cookie sessionStorage localstorage

都是浏览器本地存储

image.png cookie、localStorage 以及 sessionStorage 的异同点:

cookie:

用于浏览器和服务器通信的,由服务器生成,存储在浏览器中。

blog.csdn.net/weixin_4497…

服务器发给浏览器的一小块数据(4kb以内)(响应头里的set-cookie),下次发送给同一个域名时请求头中带上cookie,服务器就可以判断请求来自同一浏览器。

cookie不支持跨域,每个cookie绑定给指定域名。

使用:记住密码免登录;记录用户偏好进行个性化推荐

localStorage和sessionStorage:

不参与和服务器的通信

分类生命周期存储容量存储位置操作
cookie通过设置过期时间控制4KB保存在客户端,每次请求时都会带上document.cookie
localStorage理论上永久有效的,除非主动清除。约5MB保存在客户端,不与服务端交互。localStorage.getItem()/setItem()
sessionStorage仅在当前网页会话下有效,关闭页面或浏览器后会被清除。约5MB保存在客户端,不与服务端交互。sessionStorage.getItem()/setItem()

localStorage 适合持久化缓存数据,如token、用户偏好;

sessionStorage 适合保存一次性数据,适合单页页面,关闭之后不需要但刷新前仍需要的,比如存表单信息。

axios二次封装

二次封装axios 添加请求和响应拦截器

const service = axios.create({
    baseURL: "/api", // 基础路径
    timeout: 15000   // 连接请求超时时间
})

// 添加请求拦截器 
service.interceptors.request.use((config) => {
    // 显示请求中的水平进度条
    NProgress.start()
    /* 每次请求总是携带用户临时ID(不管是否登陆) */
    config.headers['userTempId'] = store.state.user.userTempId
    // 有token的话 请求头要加上token
    if(store.state.user.userInfo.token){
        config.headers['token'] = store.state.user.userInfo.token
    } 
    // 必须返回配置对象
    return config
})
//响应拦截器
service.interceptors.response.use((response) => {
//返回状态码为2xx的进入成功回调
    // 隐藏进度条
    NProgress.done()
    // 返回响应体数据
    return response.data
}, (error) => {
//响应状态码为2xx以外的进入失败回调
    // 隐藏进度条
    NProgress.done()
    // 统一处理一下错误
    alert( `请求出错: ${error.message||'未知错误'}`)
    // 后面可以选择不处理或处理
    return Promise.reject(error)
})

配置代理服务器解决跨域

vue.config.js里 配置代理服务器,对请求路由以'/api'开头的请求转发到目标服务器url

代理服务器和我们同源,这样我们可以去代理服务器取数据。

服务器与服务器之间不用ajax请求,没有跨域问题。

  devServer: {
    proxy: {
      '/api': { // 只对请求路由以/api开头的请求进行代理转发
        target: 'http://gmall-h5-api.atguigu.cn', // 转发的目标url
        changeOrigin: true // 支持跨域
      }
    }
  },

引:ajax跨域 JSONP等等

轮播图 nextTick

nextTick 数据更新后 dom的渲染是异步的 nextTick用来写操作更新后的dom的

用swiper插件做

watch banners监听banners数据 然后在watch里写一个this.$nextTick()

遇到的问题 直接写肯定是操作不到dom数据也生成不了swiper

search

search通过操作面包屑导航 来实时修改search页的展示数据

向后台发post请求

配置options 搜索请求

面包屑每次修改之后 修改options的内容 都重新发请求this.dispatch('..',options) 然后存到vuex的state里

selector 遍历prop属性展示

options初始化: 通过路由 解构赋值 this.options = {...this.options,}或者用object.assign合并

如果修改了路由里的东西 要改路由 然后用replace 重跳一下 还要重新发一次请求 这逻辑都好简单。。

删对象属性 delete obj[key]

路由相关

params 要占位 /search/:ID? (?代表可传可不传) 在url里是 /search/123 这样 要配合name传参

query 不占位 在url是/search?id=123这样

放大镜zoom 和 imagelist

两者之间传值 用全局事件总线

因为是zoom接受数据 所以在zoom里on绑定事件和回调

在imagelist里不断触发事件 来传当前的图片

图片懒加载

juejin.cn/post/710073… 图片懒加载 按需加载 原理是把img图片的真实请求url写到自定义属性data-src里 src属性都统一请求一个很小的透明图片 然后监听滚动事件 判断图片在视口时再把真实url赋值给src去发请求。

实现方法:

1.getCliendBoundingRect()

判断是否在视口内函数:用getCliendBoundingRect()方法 返回一个对象有top left width height等属性

获取图片相对视口左上角的top left值 和自身的宽高 width height 和视口的宽高 window.innerHeight window.innerHeightWidth

在视口内:top+height >=0 && top<= window.innerHeight &&...

懒加载函数:获取所有lazy类的图片存入数组(Array.from从类数组生成数组) 遍历数组 逐个判断是否在视口内 如果是视口内就把data-src的真实url赋值给src属性 并移除lazy类和data-src

监听scroll事件,绑定节流处理的懒加载函数:document.addEventListener('scroll',throttle(lazyload,1000))

弊端:引起重绘和回流 需要自己手动计算+绑定事件

  1. IntersectionObserver API 可以返回一个观察器 自动观察元素是否可见
function lazyLoadWithObserver() {
    // 推荐使用IntersectionObserver
    let observer = new IntersectionObserver((entries, observe) => {
        entries.forEach(item => {
            // 获取当前正在观察的元素
            let target = item.target
            // 在视口内
            if(item.isIntersecting && target.dataset.src) {
                    target.src = target.dataset.src
                    // 删除data-src属性
                    target.removeAttribute('data-src')
                    // 取消观察
                    observe.unobserve(item.target)
                
            }
        })
    })

    let imgs = document.querySelectorAll('.lazy')

    imgs.forEach(item => {
      // 遍历观察元素
        observer.observe(item)
    })
}
lazyLoadWithObserver()

路由懒加载

简单说:把路由对应组件分开打包成代码块 访问该路由的时候再加载组件

原理是传一个import函数给路由component属性

vue是单页面应用,直接用import from 的话 运用webpack打包后,一般会放在一个单独的js文件中,不用懒加载的话会变得非常大。路由懒加载是把不同路由对应的组件分割成不同的代码块,然后当路由被访问的时候才加载对应组件。

原理:import(路径)webpack会单独打包 import函数

常用:箭头函数+ES6的import()函数实现:component: ()=>import(...) 传一个函数给component

路由守卫

全局: 全局前置beforeEach 全局解析 beforeResolve 全局后置afterEach 路由专属 beforeEnter 组件专属 beforeRouteEnter Update Leave

遇到的问题

1.swiper创建 配合nexttick 2.三级导航的卡顿现象 防抖节流 + 用了事件委托来优化 3.当从页面跳转到新路由时,滚动条保持原有位置

难点:

不说难点说我遇到的问题

//配置路由
export default new VueRouter({
    routes,
    scrollBehavior (to, from, savedPosition) {
        return {x:0,y:0} //每次路由切换时的滚动条位置
    }
})