4-1 跨域-CORS
前端跨域解决方案
跨域是浏览器为了安全而作出的限制策略:防止其他人随意篡改、抓取你的数据
浏览器请求必须遵循同源策略:同域名、同端口、同协议,其中一个不同,别人无法请求你的接口
- CORS跨域
- JSONP跨域
- 代理跨域
CORS跨域-由服务端设置,前端直接调用;后台允许前端某个站点进行访问
#安装依赖 --save保存到配置文件 -dev保存到开发环境 package.json
npm i axios --save-dev
以Easy-Mock为例,就是CORS跨域,任何网站都可以调用接口,或者指定只有某个域名的网站才可以调用。
注册Easy-Mock之后,会自动生成示例项目,用query接口进行测试。代码中的url就是easy-mock中项目的url。
Access-Control-Allow-Credentials:true 允许跨域的时候,将前端的cookie传过去。如果取不到userid或者cookieid的时候,需要设置这句话
4-2 跨域-JSONP
前后端适配,后台配合;前后台同时改造。
#安装依赖
npm i jsonp --save-dev
#在App.vue中导入jsonp,注释掉axios
import jsonp from 'jsonp'
修改APP.vue的mounted()方法
mounted(){
let url = "https://www.easy-mock.com/mock/5e64d55b8e711c50e7d3311b/example/query#!method=get";
jsonp(url,()=>{
})
}
jsonp实际上不是一个请求,而是一段JS脚本,所以在XHR中找不到,需要在JS中找.
但是这样无法体现jsonp的跨域,因为easy-mock允许任何人调用接口. 现在来调用mooc网的接口
现在App.vue中的接口换成上面这个.
4-3 跨域-接口代理
接口代理-通过修改nginx服务器配置来实现。
本地开发环境中用nodejs服务器,上线一般用nginx服务器。
不用修改前后端,只要运维团队修改服务器配置。
创建一个vue.config.js,名字必须是这个,通过这个配置文件,将服务器配置传到nodejs服务器中。
//vue.config.js的内容
module.exports = {
//必须用devServer命名,服务器会读取这个配置
devServer:{
host:'localhost',
port:8080,
proxy:{
//拦截 common进行将localhost:8080换成www.imooc.com
'/common':{
target:'https://www.imooc.com',
changeOrigin:true,
pathRewrite:{
'/common':'/common'
}
}
}
}
}
同时修改vue.js中的请求地址
let url = "/common/adver-getadver";
这样,虽然访问的是localhost:8080,但是已经获取到了mooc的资源
为了避免每一个地址都要设置代理转发,可以设置一个统一的拦截地址,然后置空
4-4 接口梳理
- 熟悉文档、查看原型、读懂需求
- 了解前端设计稿-设计前端业务架构
- 了解后台接口文档-制定相关对接规范
- 协调资源
- 搭建前端架构
#业务规范
{
"sattus": 0,
"data": {}
}
4-5 目录结构设置
拿到设计稿之后分析,需要多少页面,如何设置路由,哪些页面部分可以抽取出来形成组件进行复用。
public目录是下面有图片,mock。
resource里面放的是文档,软件等等;
分析设计稿 页面
首页:顶部导航展开页
首页:左侧菜单展开页
产品站:商品大图介绍
产品详情(产品购买页)
订单列表
订单列表 无数据
登录页面
我的购物车,确认订单,订单结算,订单结算-展开详情,订单支付,订单列表,顶部的组件是一样的
src的目录结构
src/assets:放置静态图片,大的图片放在public目录下,因为请求图片会有请求;而assets中的icon图片、css图片等小图片会打包成bit64,减少请求,性能最优。
src/components 放置一些组件
App.vue是根组件,里面放<router-view></router-view>,这个用来加载所有的页面视图
src/api 接口文件夹
src/util 公共的方法 如数据转换等
src/storage 数据存储的工具箱 如怎么存值 怎么取值
src/store vuex会用到
router.js 承载路由的文件
src/pages 承载页面
components/home.vue home主页的组件的基础,把每一页的组件集成,就不用在每一页上重复开发了.
detail.vue \index.vue\ product.vue 嵌套到home.vue的router-view当中
而订单,订单确认,订单支付,也需要有一个像home那样的主结构;所以,order.vue作为他们的主视图
登录页面是单独的login.vue
从当前页面到支付宝页面的中转页面 alipay.vue
4-6 基本插件介绍
安装项目依赖:之前,已经安装了一些依赖
图片需要懒加载vue-lazyload 需要element-ui 一键修改页面主题 node-sass sass-loader 图片轮播 vue-awesome-swiper 使用axios更方便 vue-axios 前端页面与后台的通信vue-cookie 。最好分开安装,可以及时反馈安装是否成功
安装依赖前 npm install,避免出现找不到文件夹等问题
安装前的准备工作与具体安装
https://blog.csdn.net/MyQGirl666/article/details/104957736
npm i vue-lazyload element-ui node-sass sass-loader vue-awesome-swiper vue-axios vue-cookie --save-dev
4-7 路由封装
用vue的方式加载
订单和首页用的不是同一个父路由,他们顶部和底部的组件不一样。
在router.js中定义路由,在main.js中加载使用
在main中引入router,如果引入的名字是一样的,可以key-value可以省略value,直接写 router,
如果引入的是import routers from './router', new Vue中就应该写router:routers
组件名开头大写,其他的小写
home.vue
<template>
<div>
<!-- 这里写nav-header,以为NavFooter.vue中export中的name是这个 -->
<nav-header></nav-header>
<router-view></router-view>
<nav-footer></nav-footer>
</div>
</template>
<script>
import NavHeader from './../components/NavHeader'
import NavFooter from './../components/NavFooter'
export default{
name:'nav-home',
components:{
NavHeader,//因为import导入的是NavHeader
NavFooter
}
}
</script>
NavHeader.vue
<template>
<div>nav-header</div>
</template>
<script>
export default{
name:'nav-header',
}
</script>
NavFooter.vue
<template>
<div>nav-footer</div>
</template>
<script>
export default{
name:'nav-footer'
}
</script>
默认访问index,在router.js中加入
redirect:'/index',
nav-header与nav-footer都已经引入到home.vue中了,只需要关心router-view中的开发就行了。
index.vue中的代码
<template>
<div>
index
</div>
</template>
<script>
export default {
name:'index'
}
</script>
会自动渲染home部分(包括nav-header,nav-footer),只需要关心index如何开发即可。同样,复制同样的代码到product,detail
但是购物车、订单支付、订单确认,不会再用nav-header nav-footer那套结构,统一建一套新结构。
在order.vue OrderHeader.vue写代码
单独给car.vue一个结构
orderList.vue 父路由是order,所以一定会加载order的组件,而order里面又包括了order-header和nav-footer组件
orderConfirm.vue orderPay.vue alipay.vue 也是一样
4-8 Storage封装
cookie、 localStorage、sessionStorage三者区别
存储大小:Cookie 4K、Storage 5M
有效期:Cookie拥有有效期 过期自动清除,localStorage永久储存,sessionStorage存储在内存,关闭窗口就没有了
Cookie会发送到服务器端(服务器自己去浏览器端取的,用来区分用户),存储在内存中,也会写在本地,Storage只存储在浏览器端
路径:Cookie有路径限制(可以在www.baidu.com/a下面有,但是www.baidu.com/b下面没有),Storage只存储在域名下(www.baidu.com下的 所有路径都会有)
API:Cookie没有特定的API ,Storage有对应的API
把整个一大段JSON报文存储,用cookie不合适,用Storage。
为什么要封装Storage,本身不是已经有API吗
Storage本身有API,但只是简单的key/value形式
Storage只存储字符串,需要人工转换成json对象
Storage只能一次性清空,不能单个清空
接下来写src/storage/index.js
vue.config.js写成comment规范,是给webpack用的,index.js写成ES6规范
获取整个数据
//获取整个数据
getStorage() {
return JSON.parse(window.sessionStorage.getItem(STORAGE_KEY) || '{}');
},
在浏览器中测试
value值部分的条目都用双引号,字符串jack也用双引号
获取值需要有key,这个key不是最外面的mall,而是user,或者其他里面的,比如要获取到user
getItem(key){
return this.getStorage()[key];
}
如果要获取userName,需要将userName作为key,user作为模块。
getItem(key,module_name){
if(module_name){
//返回的是object
let val = this.getItem(module_name);
if(val)return val[key];
}
return this.getStorage()[key];
}
设置值,如果是与user同级
setItem(key,value){
let val = this.getStorage();
val[key] = value;
//覆盖进去
window.sessionStorage.setItem(STORAGE_KEY, JSON.stringify(val));
}
如果是不同级
// 存储值
setItem(key, value, module_name) {
if (module_name) {
let val = this.getItem(module_name);
val[key] = value;
this.setItem(module_name, val);
} else {
let val = this.getStorage();
val[key] = value;
//覆盖进去
window.sessionStorage.setItem(STORAGE_KEY, JSON.stringify(val));
}
}
清除功能也是一样
//清空某一个值
clear(key, module_name) {
let val = this.getStorage();
if (module_name) {
if (!val[module_name]) return;
delete val[module_name][key];
} else {
delete val[key];
}
window.sessionStorage.setItem(STORAGE_KEY, JSON.stringify(val));
}
在App.vue中导入这个storage,
import storage from './storage/index'
mounted(){
storage.setItem('a',1)
// storage.setItem('user',{a:1})
}
storage.setItem('user',{a:1})
但是,这样覆盖了之前的user数据,如果是想要在之前的数据基础之上添加新数据,需要modle_name
storage.setItem('abc',{a:1},'user')
删除a项目
storage.clear('a')
删除user下面的a