• 简历考察点1_《基于 VUE2.0 前后端分离的个人博客系统》


    项目名称:《基于 Vue2.0前后端分离的个人博客系统》
    项目描述:提供最新技术资讯、开发知识和分享的博客平台,功能模块包括:支持不同用户登录注册、编辑并发布博客、上传图片、评论留言、根据访问量查询最热文章和标签、根据日期顺序对文章进行归纳,并在 服务器上部署 运行。
    主要工作: 
    1. 使用 Element-UI 快速搭建页面。自定义 components 通用组件,设置 article、card、comment 等界面相关功能;
    2. 对 axios 进行二次封装 请求拦截器、响应拦截器 等处理用户登录状态;使用 token 进行身份认证 对异常情况统一处理;
    3. 使用 vuex 对博客进行全局状态管理 session/storage 存储数据 ,在更新时异步与后台数据同步;
    4. 构建 git 仓库进行项目管理 ,对项目运行过程中遇到的 跨域问题 网页执行异常 启动数据变慢 等问题的排查和解决有一 定的了解。
    技术栈:Vue2、Vue-Router、axios、Webpack、Element-UI

    考察点:

    ① Vue2.0:

    (1)Vue的生命周期?

    (2)Vue 和 React的区别?

    (3)Vue 的双向数据绑定原理?

    (4)Vue2 和 Vue3 的区别?

    (5)Vue组件通信常用方式?

    (6)Vue中computed和watch的区别,那个可以进行异步操作?

    (7)Vue的状态管理模式?

    (1)Vue的生命周期?
    生命周期描述
    beforeCreate组件实例被创建之初
    created组件实例已经完全创建
    beforeMount组件挂载之前
    mounted组件挂载到实例上去之后
    beforeUpdate组件数据发生变化,更新之前
    updated组件数据更新之后
    beforeDestroy组件实例销毁之前
    destroyed组件实例销毁之后
    activatedkeep-alive 缓存的组件激活时
    deactivatedkeep-alive 缓存的组件停用是调用
    errorCaptured捕获一个来自子孙组件的错误时被调用
     (2)Vue 和 React的区别?

    ① 监听数据变化的实现原理不同

    vue 使用代理/拦截的方式,通过getter/setter 以及修改data就能精准知道数据变化,而react使用setState api来实现。vue要知道修改了哪些内容通过watch/computed等钩子供开发人员使用,但react需要通过业务逻辑层diff才知道。

    ② 数据绑定不同

    vue是双向绑定,vue最核心的功能有两个:一是响应式的数据绑定系统,二是组件系统。

    ③ 组件通信不同

    Vue中有三种方式可以实现组件通信:

    • 父组件通过props向子组件传递数据或者回调,虽然可以传递回调,但一般只传数据;
    • 子组件通过事件向父组件发送消息;
    • 通过V2.0中新增的provide/inject来实现父组件向子组件注入数据,可以跨越多个层级。

    React中也有对应的三种方式:

    • 父组件通过props可以向子组件传递数据或者回调;
    • 可以通过 context 进行跨层级的通信,这其实和 provide/inject 起到的作用差不多。

    ④ 框架本质不同

    Vue本质是MVVM框架,由MVC发展而来;

    React是前端组件化框架,由后端组件化发展而来。

    react和vue的优缺点

    Vue的优缺点:简单、快速、强大、对模块友好,但不支持IE8。

    React的优缺点:速度快、跨浏览器兼容、模块化;但学习曲线陡峭,需要深度的知识来构建应用程序。

    (3)vue的双向数据绑定原理?

    vue 的双向绑定由三个重要部分构成:数据层Model、视图层View、业务逻辑层ViewModel

    • 数据层(Model):应用的数据及业务逻辑
    • 视图层(View):应用的展示效果,各类UI组件
    • 业务逻辑层(ViewModel):框架封装的核心,它负责将数据与视图关联起来

    ViewModel:由两个主要部分组成

    监听器(Observer):对所有数据的属性进行监听。

    解析器(Compiler):对每个元素节点的质量进行扫描根解析,根据指令模版替换数据,以及绑定相应的更新函数。

    双向绑定:(发布订阅 更新回调)

    1. new Vue()首先执行初始化,对data执行响应化处理,这个过程发生Observe
    2. 同时对模板执行编译,找到其中动态绑定的数据,从data中获取并初始化视图,这个过程发生在Compile
    3. 同时定义⼀个更新函数和Watcher,将来对应数据变化时Watcher会调用更新函数
    4. 由于data的某个key在⼀个视图中可能出现多次,所以每个key都需要⼀个管家Dep来管理多个Watcher
    5. 将来data中数据⼀旦发生变化,会首先找到对应的Dep,通知所有Watcher执行更新函数
    (4)vue2 和 vue3的区别?

     https://blog.csdn.net/m0_64346035/article/details/124855972

    1.vue2和vue3的双向数据绑定原理发生了改变。

    vue2 双向数据绑定是利用ES5中的一个API Object.definePropert()对数据进行劫持 结合 发布订阅模式的方式来实现的。

    vue2的双向数据绑定原理通过object.defineProperty中的set方法来实现数据劫持,但是无法监听数组内部的数据变化)

    vue3 使用ES6语法的proxy对象来实现双向数据绑定的,可以检测到数组内部数据的变化。

    Proxy用于修改某些操作的默认行为,相当于在目标对象之前架设一层拦截,外部所有的访问都必须先通过这层拦截,因此提供了一种机制,可以对外部的访问进行过滤和修改。

    2. vue3支持碎片化(Fragments)

    1. // vue2
    2. // vue3
    3. <template>
    4. <div class='form-element'>
    5. div>
    6. <h2> {{ title }} h2>
    7. template>

    3. Composition API

    Vue2 与vue3 最大的区别是vue2使用选项类型api,对比vue3合成型api

    旧得选项型api在代码里分割了不同得属性:data,computed,methods等;

    4. 建立数据data

    vue2-把数据放入data属性中

    1. export default {
    2. props:{
    3. title: String
    4. },
    5. data(){
    6. return {
    7. username: '',
    8. password: ''
    9. }
    10. }
    11. }

     在Vue3.0 需要使用一个新的setup() 方法,次方法在组件初始化构造时触发。

    1. import { reactive } from 'vue'
    2. export default {
    3. props: {
    4. title: String
    5. },
    6. setup(){
    7. const state = reactive({
    8. username: '',
    9. password: ''
    10. })
    11. return { state }
    12. }
    13. }

    5. 生命周期钩子 Hooks

    Vue2Vue3
    beforeCreatesetup()
    createdsetup()
    beforeMountonBeforeMount
    MountedonMounted
    beforeUpdateonBeforeUpdate
    updateonUpdated
    beforeDestroyonBeforeUnmount
    destroyedonUnmountd
    activateonActivated
    deactivateonDeactived
    (5)Vue组件通信常用方式?

    组件间通信分类可以分为:

    · 父子组件之间的通信

    · 兄弟组件之间的通信

    · 祖孙与后代组件之间的通信

    · 非关系组件间的通信

    Vue的8种通信方案:

    1. 通过props 传递

    2. 通过$emit 触发自定义事件

    3. 使用ref

    4. EventBus

    5. parent 或 root

    6. attrs 或 listeners

    7. Provide 与 inject

    8. Vuex

    (6)Vue中computed和watch的区别,那个可以进行异步操作?

    · computed 是计算属性,依赖其他属性计算值,并且 computed 的值有缓存,只有当计算值变化才会返回内容。

    · watch 监听到值的变化就会执行回调,在调用中可以进行一些逻辑操作。

    所以一般来说,需要依赖别的属性来动态获得值的时候可以使用computed,对于监听到值的变化需要做一些复杂业务逻辑的情况可以使用 watch

    另外 computer 和 watch 还都支持对象的写法,这种方式知道的人并不多。

    (7)Vue的状态管理模式?

    ② 服务器上部署

    ① 购买阿里云域名和远程服务器,进行域名解析和实名制认证;

    将前端项目npm run build打包之后生成一个dist文件夹(静态文件 - 静态文件是经过压缩的,所以代码加载速度更快),

    ② 然后把这个文件夹放在服务器上一个目录下,记住这个目录路径,开一个对应的端口号。

    ③ 然后在nginx配置中将这个端口号和路径进行映射(nginx前端配置),再重启nginx就可以了(解决前后端跨域问题)。

    ④ 再进入前端页面即可。

    ③ Element-UI 搭建Component组件(三栏布局 十二分栏布局如何实现)

    三栏布局:

    • 两边使用 float,中间使用 margin
    • 两边使用 absolute,中间使用 margin
    • 两边使用 float 和 负 margin
    • display:table 实现
    • grid 网格布局

    ④ axios 进行二次封装,⑤ 设置请求拦截器、响应拦截器

    对 axios 进行二次封装,设置request拦截器请求token进行异步处理,对身份进行认证;设置response拦截器作全局状态统一处理,根据请求得到的res.code状态码判断用户登录情况,并给出提示;

    axios 是一个轻量级的 Http 客户端,基于XMLHttpRequest服务来执行Http请求,支持丰富的配置,支持Promise,支持浏览器端和Node.js端。

    特性:

    • 从浏览器中创建 XMLHttpRequests
    • 从 node.js 创建 http请求
    • 支持 Promise API
    • 拦截请求和响应
    • 转换请求数据和响应数据
    • 取消请求
    • 自动转换JSON 数据
    • 客户端支持防御XSRF

    设置 请求头、状态码state、请求方法 get/post、请求拦截器(根据请求的请求头设定,来决定哪些请求可以访问)、响应拦截器(根据后端返回的状态码判定执行不同的业务)

    1. // 发送请求
    2. import axios from 'axios'
    3. axios(config) // 直接传入配置
    4. axios(url[ , config]) // 传入url和配置
    5. axois[method](url[, option]) // 直接调用请求方式方法,传入url和配置
    6. axois[method](url[, data[, option]]) // 直接调用请求方式方法,传入data、url和配置
    7. axois.request(option) // 调用request方法
    8. const axiosInstance = axois.create(config)
    9. // axiosInstance 也具有以上 axios 的能力
    10. axios.all([axiosInstance1, axiosInstance2]).then(axios.spread(response1, response2))
    11. // 调用 all 和传入 spread 回调
    12. // 请求拦截器
    13. axois.interceptors.request.use(function(config){
    14. // 写发送请求前处理的代码
    15. return config;
    16. },function(error){
    17. // 写发送请求错误相关的代码
    18. return Promise.reject(error);
    19. });
    20. // 响应拦截器
    21. axois.interceptor.response.use(function(response){
    22. // 这里写得到响应数据后处理的代码
    23. return response;
    24. }, function(error){
    25. // 这里写错误响应处理的代码
    26. return Promise.reject(error);
    27. });

    《程序喵》项目的请求/响应处理: 

    1. // import axios from 'axios'
    2. // import {Message} from 'element-ui'
    3. import store from '@/store'
    4. import {getToken} from '@/request/token'
    5. const service = axios.create({
    6. baseURL: process.env.BASE_API,
    7. timeout: 10000
    8. })
    9. //request拦截器
    10. service.interceptors.request.use(config => {
    11. if (store.state.token) {
    12. config.headers['Oauth-Token'] = getToken()
    13. }
    14. return config
    15. }, error => {
    16. Promise.reject(error)
    17. })
    18. // respone拦截器
    19. service.interceptors.response.use(
    20. response => {
    21. //全局统一处理 Session超时
    22. if (response.headers['session_time_out'] == 'timeout') {
    23. store.dispatch('fedLogOut')
    24. }
    25. const res = response.data;
    26. //0 为成功状态
    27. if (res.code !== 200) {
    28. //90001 Session超时
    29. if (res.code === 90001) {
    30. return Promise.reject('error');
    31. }
    32. //20001 用户未登录
    33. if (res.code === 90002) {
    34. this.$message({
    35. type: 'warning',
    36. showClose: true,
    37. message: '未登录或登录超时,请重新登录哦'
    38. })
    39. return Promise.reject('error');
    40. }
    41. //70001 权限认证错误
    42. if (res.code === 70001) {
    43. this.$message({
    44. type: 'warning',
    45. showClose: true,
    46. message: '你没有权限访问哦'
    47. })
    48. return Promise.reject('error');
    49. }
    50. return Promise.reject(res.msg);
    51. } else {
    52. return response.data;
    53. }
    54. },
    55. error => {
    56. this.$message({
    57. type: 'warning',
    58. showClose: true,
    59. message: '连接超时'
    60. })
    61. return Promise.reject('error')
    62. })
    63. export default service

    简易版 axois:

    1. class Axios {
    2. constructor() {
    3. }
    4. request(config) {
    5. return new Promise(resolve => {
    6. const {url = '', method = 'get', data = {}} = config;
    7. // 发送ajax请求
    8. const xhr = new XMLHttpRequest();
    9. xhr.open(method, url, true);
    10. xhr.onload = function() {
    11. console.log(xhr.responseText)
    12. resolve(xhr.responseText);
    13. }
    14. xhr.send(data);
    15. })
    16. }
    17. }

    ⑤ 登录过程 即 过滤拦截器的使用: 

    若依登陆过程及过滤器拦截器的使用:

    用户登陆接口:

    1、 把用户信息通过uuid即token作为key,存储在缓存中,并设置过期时间。

    2、通过jwt存储token,userId,userName在map中,设置过期时间,通过jwt(Json Web Token)创建一个编码后 access_token和expireTime,并返回token在前端。

    3、过滤器:用户前端传递的access_token通过Jwt解析,尝试获取userkey(即token),userid,username并判断是否过期,为空等。如果异常即刻报错,否则将解析的userkey,userid,username纳入请求头中,请求接着交给拦截器。

    4、拦截器:拦截器从请求头中获取userkey,userid,username,通过userkey从缓存中获取用户信息,并刷新缓存中用户信息的过期时间。并将用户信息加入到本地的  TransmittableThreadLocal>中,方便用户获取当前用户信息。

    ⑥ token进行身份认证

     https://blog.csdn.net/qq_19322833/article/details/127152528

    token 的登录流程:

    1. 客户端用账户密码请求登录;

    2. 服务器收到请求后,需要去验证账号密码;

    3. 验证成功之后,服务端会签发一个token,把这个 token 发送给客户端;

    4. 客户端收到 token 后保存起来,可以防止 cookie 也可以是 localstorage;

    5. 客户端每次向服务器发送请求资源的时候,都需要携带这个 token;

    6. 服务器收到请求,接着去验证客户端里的 token,验证成功后才会返回客户端请求的数据。

    => 根据《程序喵》项目做对应说明:(这个流程 要改)

    本地对 登录注册的username和password是通过session还是cookie哪一种方式进行存储的?

    vue项目解决思路:

    前端:vue2、vue-router、axios

    后端:Node.js、express-generator、jsonwebtoken

    前端方面:用到vue-router导航守卫Axois的请求拦截器,前者主要验证用户是否登录,后者主要实现验证token是否过期

    将token存放到localStorage 通过封装好的Axios方法获取到后端返回的 token 并存入 localStorage

    1. this.$network({
    2. url: `adminLogin?account=${form.account}&password=${form.password}`,
    3. }).then((res) => {
    4. // 判断请求是否正常请自行发挥
    5. if (res.code == 200) {// 如果正常
    6. //将后端返回的token存入localStorage
    7. localStorage.setItem("token", res.token);
    8. }
    9. })

    vue-router的导航守卫:router.beforeEach

    通过导航守卫进行 本地是否登录判断,判断当前页面是否是登录注册页(或其他需要排除的页面),如果是 则进行是否 已登录 验证;如果不是,则进行是否未登录验证。

    1. // 注:这里我们使用的是 `router.beforeEach`
    2. if (to.fullPath == '/login') {// 排除页面
    3. if (localStorage.getItem('token') != null) {
    4. console.log('您已登录,是否访问首页?');
    5. }
    6. } else if (localStorage.getItem('token') == null) {
    7. // 如果访问的是其它路由页面而且token不存在,即为未登录
    8. localStorage.clear();// 清除一次 localStorage
    9. console.log('您未登录,是否访问登录页?');
    10. return
    11. }

    Axio的拦截器 通过axois的请求拦截器interceptors 进行请求前、请求后的事件。

    请求前:interceptors.request 首先需要在 请求前 interceptors.request 里将 token 放到 headers中的Authorization中 ,以便 每次发起网络请求时携带

    1. // 请求前 interceptors.request
    2. config.headers.Authorization = localStorage.getItem("token");

    请求后:请求后 interceptors.response 里进行token是否过期验证

    1. // 请求后 interceptors.response
    2. if (window.location.pathname != '/login') {// 排除页面
    3. if (res.data.loginStatus == false) {// 如果token已过期
    4. localStorage.clear();// 清除一次 localStorage
    5. console.log('登录状态已失效,是否访问登录页?');
    6. }
    7. }

    后端方面:使用Node.js 实现

    1. // token验证,生成时和请求验证时的都可以调用!返回token状态,false为已过期
    2. function tokenVerify(token) {
    3. let status;
    4. jwt.verify(token, 'userLogin', (err, data) => {
    5. if (err) {// 过期token
    6. status = false
    7. } else {// 有效token
    8. status = true
    9. }
    10. })
    11. return status
    12. }
    13. // token生成,只用于登录时调用!通过调用token验证函数,判断token是否过期,
    14. // 若未过期,则返回true,前端token值不变;若过期,则重新生成,前端重新保存token
    15. function tokenGenerate(token, account, password, time) {
    16. let status = tokenVerify(token);
    17. if (status) {// 若token未过期
    18. token = true;
    19. } else {// 若token已过期
    20. token = jwt.sign({
    21. account: account,
    22. password: password },
    23. 'userLogin', { expiresIn: time });
    24. }
    25. return token
    26. }

    ⑦ vuex 对博客进行全局状态管理

    还可以使用react-redux进行全局状态管理。

    1. import Vue from 'vue'
    2. import Vuex from 'vuex'
    3. Vue.use(Vuex)
    4. export default new Vuex.Store({
    5. //数据,相当于data
    6. state: {
    7. //数据源 提供唯一的公共数据源,所有共享的数据统一放到store的state进行储存,相似data.
    8. },
    9. getters: {
    10. //类似于vue中的computed,进行缓存,对于Store中的数据进行加工处理形成新的数据
    11. },
    12. //里面定义方法,操作state方发
    13. mutations: {
    14. //每个 mutation 都有一个字符串的事件类型 (type)和一个回调函数 (handler)
    15. },
    16. // 操作异步操作mutation
    17. actions: {
    18. //进行异步操作
    19. },
    20. modules: {
    21. //Vuex 允许我们将 store 分割成模块(module)。每个模块拥有自己的 state、mutation、action、getter、甚至是嵌套子模块——从上至下进行同样方式的分割
    22. },
    23. })

     ⑧ session/storage 存储数据

     Cookie、sessionStorage和localStorage的区别

    (一)Cookie、sessionStorage和localStorage的区别

    共同点:都是保存在浏览器端,且同源的。

    区别:

    1. cookie数据始终在同源的http请求中携带,即 cookie在浏览器和服务器间来回传递,而sessionStorage和localStorage不会自动把数据发送给服务器,仅在本地保存。

    1. 存储大小限制:cookie数据不能超过4k,只适合保存很小的数据,如会话标识。sessionStorage和localStorage可以达到5M或更多。

    1. 数据有效期不同:sessionStorage:仅在当前浏览器窗口关闭之前有效;localStorage:始终有效,窗口或浏览器关闭也一直保存,因此作用更持久;cookie:只在设置的cookie国企时间之前有效,即使窗口关闭或浏览器关闭。

    1. 作用域不同:sessionStorage:不在不同的浏览器窗口中共享,即使是同一个页面;localstorage在所有同源窗口中都是共享的;cookie在所有同源窗口中都是共享的。

    cookie和session的区别

    1、数据位置:cookie数据存放在客户的浏览器上,session数据放在服务器上

    2、安全性:cookie不是很安全,别人可以分析存放在本地的cookie并进行cookie欺骗,考虑到安全应

    当使用session

    3、性能:session会在一定时间内保存在服务器上,当访问增多,会比较占用你服务器的性能,考虑到

    减轻服务器性能方面,应当使用cookie

    4、数据量:单个cookie保存的数据不能超过4K,很多浏览器都限制一个站点最多保存20个cookie

    5、信息存放:建议将登录信息等重要信息存放为session,其他信息如果需要保留,可以放在cookie中

    6、保存位置:session保存在服务器,客户端不知道其中的信心;cookie保存在客户端,服务器能够知

    道其中的信息

    7、保存对象:session中保存的是对象,cookie中保存的是字符串

    8、路径:session不能区分路径,同一个用户在访问一个网站期间,所有的session在任何一个地方都可

    以访问到,而cookie中如果设置了路径参数,那么同一个网站中不同路径下的cookie互相是访问不到

    的。

    9、COOKIE:是服务端向客户端写入的小的片段信息。cookie信息保存在服务器缓存区,不会在客户端显

    现。当你第一次登陆一个网站,服务器向你的机器写得片段信息。你可以在Internet选项中找到存放

    cookie的文件夹。如果不删除,cookie就一直在这个文件夹中。

    10、session需要借助cookie才能正常工作。如果客户端完全禁止cookie,session将失效。 但是如果服务器端启用了url编码,也就是用 URLEncoder.encode()把所有的url编码了,则会在url后面出现如下类似的东西 index.jsp:jsessionid=fdsaffjdlks;jaf;lkdjsf 服务器通过这个进行session的判断。

    11、Cookie支持跨域名访问,例如将domain属性设置为“.biaodianfu.com”,则以“.biaodianfu.com”为后缀的一切域名均能够访问该Cookie。跨域名Cookie如今被普遍用在网络中,例如Google、Baidu、Sina等,而Session则不会支持跨域名访问。Session仅在他所在的域名内有效。仅运用Cookie或者仅运用Session可能完成不了理想的效果。这时应该尝试一下同时运用Cookie与Session。Cookie与Session的搭配运用在实践项目中会完成很多意想不到的效果。

    ⑨ git 仓库进行项目管理

    git init 进行Git 仓库的创建

    git add readme.md 把文件添加到版本库

    git reset --hard HEAD^ 版本回退

    git checkout -- readme.md 撤销修改

    git remote add origin git@github.com:luxinfeng/GitTest.git 添加远程库(GitHub)

    git branch dev 创建/合并分支

    ⑩ 跨域问题

    跨域问题:由于浏览器的 同源策略 限制,当一个请求url的协议、域名、端口号三者之间有任意一个与当前的url不同即为跨域。

    同源策略是一种约定,它是浏览器中最核心也最基本的安全功能。同源策略会阻止一个域的 Javascript 脚本和另一个域的内容进行交互。

    同源(即指在同一个域)就是两个页面具有相同的协议(protocol)、主机(host) 和 端口号 (port)。

    博客系统项目中出现跨域问题 是由于这是前后端分离项目,前端访问路径的端口和后端访问路径的端口不一致,因此出现了跨域问题,解决方案是对前端做跨域配置。

     常见解决跨域问题的方式:

    1. 使用 jsonp 来实现跨域请求:(jsonp函数封装)JSONP 方式实现跨域请求数据_jsonp跨域请求实现示例_TKOP_的博客-CSDN博客

    原理:通过动态构建 script 标签来实现跨域请求, 因为浏览器对 script 标签的引入没有跨域的访问限制。

    过程:通过在请求的url后指定一个回调函数,然后服务器在返回数据的时候,构建一个json数据的包装,这个包装就是回调函数,然后返回给前端。

    前端接受到数据后,因为请求的是脚本文件 所以会直接执行,这样之前定义好的回调函数就可以被调用,从而实现了跨域请求的处理。

    1. <h2>A服务器的页面h2>
    2. <button id="btn">向B发送jsonp请求button>
    3. <script type="text/javascript">
    4. var btn = document.getElementById('btn');
    5. function jsonp(options) {
    6. // 处理其他参数的拼接
    7. var params = '';
    8. for (var k in options.data) {
    9. params += '&' + k + '=' + options.data[k];
    10. }
    11. // 响应处理函数
    12. var fnName = 'myJsonp' + Math.random().toString().replace('.', '');
    13. window[fnName] = options.success;
    14. // 请求完整地址
    15. var url = options.url + '?callback=' + fnName + params;
    16. // 创建script标签
    17. var script = document.createElement('script');
    18. // 设置script标签的src属性
    19. script.src = url;
    20. // 将script标签追加到页面中
    21. document.body.appendChild(script);
    22. // 在script标签追加完成请求发送后将其删除
    23. script.onload = function() {
    24. document.body.removeChild(script);
    25. window[fnName] = null;
    26. }
    27. }
    28. btn.onclick = function() {
    29. jsonp({
    30. // 地址
    31. url: 'http://localhost:3001/jsonp3',
    32. // 其他请求参数
    33. data: {
    34. name: 'tkop',
    35. age: 18
    36. },
    37. // 响应处理函数
    38. success: function(data) {
    39. console.log(data);
    40. }
    41. })
    42. }
    43. script>

    2. 使用 CORS 的方式

    跨越资源共享CORS,它运行浏览器向跨源服务器发出 XMLHttpRequestFetch 请求。目前浏览器都支持这个功能,只需要服务器设置 Access-Control-Allow-Origin 就可以开启 CORS

    1. app.use(async (ctx, next) => {
    2. ctx.set('Access-Control-Allow-Origin', '*')
    3. ctx.set('Access-Control-Allow-Headers','Content-Type,Content-Length,Authorization,Accept,X-Requested-With')
    4. ctx.set('Access-Control-Allow-Methods', 'PUT,POST,GET,DELETE,OPTIONS')
    5. if (ctx.method === 'OPTIONS') {
    6. ctx.body = 200;
    7. } else {
    8. await next()
    9. }
    10. });

     3. 使用 Node

    同源策略是浏览器需要遵循的标准,如果是服务器 向 服务器 请求 就无需遵循同源策略。

    所以可以使用Node中间件代码(两次跨域):

    接受客户端请求 → 将请求转发给服务器 → 拿到服务器响应数据 → 将响应转发给客户端

    4. 使用代理服务器

    有跨域的请求操作时发送请求给后端,让后端代为请求,然后最后将获取的结果返回。因为服务器没有跨域接口限制。 

    1. module.exports = {
    2. NODE_ENV: '"production"',
    3. // BASE_API: '"http://www.wanqi.ink:8888"'
    4. BASE_API: '"http://8.134.24.26:8888"'
    5. }

    (11)网页执行异常

    产生的原因:语法错误、运行时错误、逻辑错误、网络错误、跨域问题、DOM操作错误、异步代码执行顺序问题、资源加载顺序问题、内存泄漏等。

    Http 状态码:

    • 1XX:表示目前是协议处理的中间状态,还需要后续操作。
    • 2XX:表示成功状态。
    • 3XX:重定向状态,资源位置发生变动,需要重新请求。
    • 4XX:请求报文有误。
    • 5XX:服务器端发生错误。
      • 101 Switching Protocols :在 HTTP 升级为 WebSocket 的时候,如果服务器同意变更,就会发送状态码为 101
      • 200 OK :请求成功状态码,响应体中含有数据。
      • 204 No Content :含义同 200 ,但是响应报文不含实体的主体部分。
      • 206 Partial Content :表示部分内容请求成功。使用场景为 HTTP 分块下载和断点续传,当 然也会带上相应的响应头字段 Content-Range
      • 301 Move Permanently :永久重定向。 HTTP 升级 HTTPS ,之前站点再也不用,那就是 301。
      • 302 Found :临时重定向。当前站点暂时不可用,那就是 302 ,后续可能换回来。
      • 304 Not Modified :当命中协商缓存时会返回这个状态码。
      • 400 Bad Request :请求无效。通常为前后端数据格式不一致或者其他原因。
      • 403 Forbidden :服务器已经得到请求,但是拒绝执行,比如没权限、法律禁止等。
      • 404 Not Found :资源未找到,服务器不存在对应的资源。
      • 500 Internal Server Error :服务器报错,有些时候可以在 Response 看到后端 PHP 等技 术的报错信息等。
      • 502 Bad Gateway :服务器正常,但是访问出错。
      • 503 Service Unavailable :服务器繁忙或者停机维护,暂时无法处理请求。
  • 相关阅读:
    LeetCode437:路径总和III
    BDD - BDD Automation Framwork 自动化框架
    题目1444:蓝桥杯201 4年第五届真题斐波那契
    centos7下部署oracle 11g
    20-算法训练营第二十天 |力扣654最大二叉树、力扣617合并二叉树、力扣98验证二叉搜索树
    大数据之巅:深入分析数据湖架构的优势
    不开辟新存储空间的情况下完成链表的逆置
    03 React 面向组件编程
    C#引用Microsoft.Office.Interop.Excel
    基于PyQt5和PSoC6的多功能平衡车设计
  • 原文地址:https://blog.csdn.net/huangyuting98/article/details/131418486