20230428----重返学习-vue项目

这篇具有很好参考价值的文章主要介绍了20230428----重返学习-vue项目。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

day-060-sixty-20230428-vue项目

vue项目

配置开发服务器

  1. 如果没有后端接口,可以直接通过浏览器控制台看到别人网站的接口。

    1. Shift+Control+I打开浏览器控制台,点击Network查看网络请求,点击Fetch/XHR,查看当前页面发送的请求。
    2. 触发请求,可以看到浏览器向别人的后端发送的请求及请求信息。
    3. 复制一下请求路径和请求方式及入参,提取如http://backend-api-01.newbee.ltd/api/v1/index-infos的url,最好一个网站仅用http://backend-api-01.newbee.ltd,即取协议到端口处,为一个代理地址的target属性。对应名可以用拼音进行分类,比如取二级域名newbee并在前面加一个斜线,为代理地址名。即确定用/newbee代理http://backend-api-01.newbee.ltd,也可以用自定义的如/NewPeak/代理http://backend-api-01.newbee.ltd。为了表示兼容和具体通用流程,这里用/NewPeak/表示。
  2. /vue.config.js中修改

    const { defineConfig } = require("@vue/cli-service");
    module.exports = defineConfig({
      devServer: {
        proxy: {
    
          // 1. 以用户发起一个请求时的url为目标路径。
          // 2. 将以`/NewPeak/`开头的目标路径为触发该代理的时机。
          "/NewPeak/": {
            target: "http://backend-api-01.newbee.ltd", // 3. 将会以`/NewPeak/`开头的目标路径添加到其开头。
            ws: true, //是否代理websockets。
            changeOrigin: true, //4. 是否伪装访问源,一般选true,否则可能请求不了。
            pathRewrite: { "^/NewPeak/": "/" }, //5. 目标路径重写。替换url,缩短原的旧标识。
    
            // pathRewrite:path=>path.replace(/^\/NewPeak\//, "/"),//目标路径重写-函数方式。
    
            // pathRewrite(path, req) {//目标路径重写-全入参。
            //   console.log("path", path, `;${path.replace(/^\/NewPeak\//, "/")}`);
            //   //debugger
            //   // console.dir(req, { deep: 1 });
            //   // console.log("req", req);
            //   return path.replace(/^\/NewPeak\//, "/");
            // },
          },
    
          "/api": {
            //  /api-->http://backend-api-01.newbee.ltd/api
            target: "http://backend-api-01.newbee.ltd",
            ws: true,
            changeOrigin: true,
          },
        },
      },
    });
    
  3. 重启项目,以便让配置生效。

  4. 在项目中任意地方用/NewPeak/发起一个请求。

    fetch("/NewPeak/api/v1/index-infos")//相当于fetch(`http://backend-api-01.newbee.ltd/api/v1/index-infos`)
    /* //fetch("/NewPeak/api/v1/index-infos")
    --> 目标路径为`/NewPeak/api/v1/index-infos`
    --> `/NewPeak/`触发了`/vue.config.js`中的`module.exports.devServer.proxy["/NewPeak/"]`
    --> module.exports.devServer.proxy["/NewPeak/"].target + module.exports.devServer.proxy["/NewPeak/"].pathRewrite(`/NewPeak/api/v1/index-infos`)
    --> `http://backend-api-01.newbee.ltd` + `/NewPeak/api/v1/index-infos`.replace(/^\/NewPeak\//, "/")
    --> `http://backend-api-01.newbee.ltd` + `/api/v1/index-infos`
    --> `http://backend-api-01.newbee.ltd/api/v1/index-infos`; */
    

配置axios

  1. 安装axios

    npm i axios
    
  2. 新建/src/http/http.js用于对axios进行二次封装文件与/src/http/index.js调用二次封装过后的axios进行接口请求,把所有的axios都封装并导出。

    • 一般是实例化一个axios实例对象出来,但这里直接对axios的原型做了处理。
      • /src/http/http.js

        // axios 二次封装文件
        import axios from "axios";
        
        
        //配置基础路径
        axios.defaults.baseURL=process.env.NODE_ENV==="production"?"XXXX":"/api/v1";// 真实项目中baseURL分开发环境和生产环境
        //生产环境 production
        //开发环境 development---目前
        
        // 添加请求拦截器
        axios.interceptors.request.use(function (config) {
          // 在发送请求之前做些什么
          let token=localStorage.getItem("xfdata");
          if(token){
            config.headers.token=token;
          }
          return config;
        }, function (error) {
          // 对请求错误做些什么
          return Promise.reject(error);
        });
        
        // 添加响应拦截器
        axios.interceptors.response.use(function (response) {
          
          return response.data;
        }, function (error) {
          // 超出 2xx 范围的状态码都会触发该函数。
          // 对响应错误做点什么
          return Promise.reject(error);
        });
        
        export default axios;
        
      • /src/http/index.js

        import http from "./http.js";
        // 拿到首页数据 - http://backend-api-01.newbee.ltd/api/v1/index-infos
        function getHomeData() {
          return http.get("/index-infos");
        }
        export default {
          getHomeData,
        };
        
  3. /src/main.js中导出/src/http/index.js中的axios接口函数集合对象,并挂载到vue原型上,以便可以在vue组件内通过this. x x x 访问到 a x i o s 接口函数集合对象,并通过 ‘ t h i s . xxx访问到axios接口函数集合对象,并通过`this. xxx访问到axios接口函数集合对象,并通过this.集合对象名.接口名访问到二次封装后axios的请求函数,如this.$api.register`。

    • /src/main.js

      import Vue from "vue";
      import api from "./http/index.js";//可以通过this.$api.xxx()调用`/src/http/index.js`中的xxx方法。
      Vue.prototype.$api = api;
      

组件抽离思路

对于差不多一致的页面,可以抽离出一个组件,进而那几个地方复用该组件。

静态文件

  • 组件中要调用的静态文件,一般放在文件夹/src/assets/中,因为这些文件不一定要调用。
    • 因为组件有些是懒加载的,组件都不加载,那就不一定会用到了。
  • 一般网站及的静态文件,放在/public/中。如/public/index.html模板或/public/favicon.ico图标。

配置前端验证码

  1. 安装vue2-verify插件。

    • 有很多前端验证插件,这里选vue2-verify;
      • vue2-verify - npm插件
    npm i vue2-verify
    
  2. 在要使用的组件中引入并使用vue2-verify。

    <template>
          <Verify @success="alert('success')" @error="alert('error')" :type="1"></Verify>
    </template>
    
    
    <script>
        import Verify from 'vue2-verify'
    
        export default {
            components: {
                Verify
            },
            methods: {
                alert(text) {
                    console.log(text)
                }
            },
        }
    </script>
    
  3. 修改Verify组件的一些参数,以得到自己想要的功能类型。

    <template>
      <Verify :type="2" :showButton="false" fontSize="18px"></Verify>
    </template>
    
  4. 修改verify组件的样式,以得到自己想要的样式。

    <template>
      <Verify @success="handleAlert('success')" @error="handleAlert('error')" :type="2" :showButton="false" fontSize="18px"></Verify>
    </template>
    
    
    <script>
      import Verify from 'vue2-verify'
    
      export default {
        components: {
            Verify
        },
        methods: {
            handleAlert(text) {
                console.log(text)
            }
        },
      }
    </script>
    <style lang="less">
    .cerify-code-panel {
      margin-top: 20px;
      margin-left: 15px;
      display: flex;
    
      .verify-code {
        width: 130px !important;
        height: 42px !important;
        line-height: 42px !important;
      }
    
      .verify-code-area {
        display: flex;
    
        .varify-input-code {
          height: 40px;
          line-height: 40px;
          width: 100px;
          margin-left: 10px;
          border: 1px solid #eee;
          font-size: 16px;
          text-indent: 10px;
        }
    
        .verify-change-code {
          font-size: 14px;
        }
      }
    }
    </style>
    

配置加密md5

  1. 安装js-md5插件。

    • 有很多前端验证插件,这里选js-md5;
      • js-md5 - npm插件
    npm i js-md5
    
  2. 在需要使用md5加密的文件中引入并使用md5加密。

    • /src/http/index.js

      import http from "./http.js";
      
      import md5 from "js-md5";
      
      // 登录接口 - http://backend-api-01.newbee.ltd/api/v1/user/login
      function login(loginName, password) {
        return http.post("/user/login", { loginName, passwordMd5: md5(password) });
      }
      export default {
        login,
      };
      

token值

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ja2JAnb0-1682697499587)(./后端返回的token的使用思路.png)]

  • token的概念
    • token是后端依据算法生成的用来表示用户登录信息的一堆字符串,它标识了用户的身份。类似于用户名及临时密码。
      • 有很多接口需要附带token信息才能拿到数据。可以理解为,有了token,在后端那边就相当于有了身份标识,后端就可以确定是那个人请求的接口,以及知道那个是是否有权限访问一些数据。
  • token在应用的整个流程思路
    1. 前端用户发起登录的请求,附带用户名及加密密码。
    2. 前端登录请求到达后端,后端根据前端的数据,判断前端用户是否登录成功。同时用一个算法得出token信息,如果用户名及密码正确,就返回token信息给前端。
    3. 前端得到token,把token存在于浏览器本地存储及vuex或全局变量或cookie等地方。并提示登录成功的相关操作,如跳转页面等。
      • 这个得看具体需求,如果需要刷新后依旧可以访问,那就只能存在于浏览器本地存储或cookie中。
    4. 前端在有token的情况下,为后续每一个请求都附加上token信息。
      • 其实可以只对特定的请求做单独处理,即有些请求放token,有些不放。但那样太麻烦,因为token在目前的前后端交互中是核心数据,一般每个请求都要写的。
        • 所以一般是每个请求都附带上token。因为有些请求,不一定能附加信息,如get请求或delete请求这一类,而token一般都要附带。故而放在请求头Response headers中比较合理。
          • 而统一对请求头做处理,axios中有一个钩子函数,即请求拦截器axios.interceptors.request.use()
    5. 如果请求过程中,发现token有问题,那么可以把token清空,并重定向到登录页,让用户登录一下。
      • 具体是什么时候有问题,一般是后端发现的,这个逻辑主要也是后端来做。
      • 可以在想要接口中做这个处理,也可以每个接口都处理。但麻烦。
        • 一般是每个接口都做,如果后端返回的code为某个值如code或resultCode为416之类的,就约定要进行清空token等操作。
          • 而统一对响应头做处理,axios中有一个钩子函数,即响应拦截器axios.interceptors.response.use()
  • 步骤
    1. 在登录页/src/views/LoginView.vue做登录操作,并处理登录成功的场景

      • /src/views/LoginView.vue核心

        <template>
          <div class="login-wrap">
            <van-nav-bar :title="flag ? `登录` : `注册`" left-arrow>
              <template #right>
                <van-icon name="ellipsis" size="18" />
              </template>
            </van-nav-bar>
        
            <div class="img-box">
              <img src="../assets/logo.png" alt="" />
            </div>
        
            <van-form @submit="onSubmit()">
              <van-field
                v-model="username"
                name="用户名"
                label="用户名"
                placeholder="用户名"
                :rules="[{ required: true, message: '请填写用户名' }]"
              />
              <van-field
                v-model="password"
                type="password"
                name="密码"
                label="密码"
                placeholder="密码"
                :rules="[{ required: true, message: '请填写密码' }]"
              />
        
              <div style="margin: 16px">
                <van-button round block type="info" native-type="submit">
                  {{ flag ? `登录` : `注册` }}
                </van-button>
              </div>
            </van-form>
          </div>
        </template>
        
        <script>
        import Verify from "vue2-verify";
        import { Notify } from "vant";
        
        export default {
          components: {
            Verify,
          },
          data() {
            return {
              username: "",
              password: "",
              flag: true,
              verifyFlag: false,
            };
          },
          methods: {
            onSubmit() {
        
              this.$api
                .login(this.username, this.password)
                .then((value) => {
                  // {"resultCode":200,"message":"SUCCESS","data":"a98cd1e0376b20776dcfb6ff8306031e"}
                  console.log(value);
                  let { resultCode, message, data } = value;
                  if (resultCode !== 200) {
                    Notify(message || "登录出错,请重试");
                    this.$refs.theVerify.refresh();
                    return;
                  }
        
                  this.username = this.password = ``;
                  Notify({ type: "success", message: "登录成功" });
                  if (data) {
                    localStorage.setItem("xfAppToken", data);
                  }
                  this.$router.push("/IndexView");
                })
                .catch((error) => {
                  console.log(`error-->`, error);
                })
                .finally(() => {
                  console.log("登录操作后执行");
                  this.$refs.theVerify.refresh();
                });
            },
          },
        };
        </script>
        
      • /src/views/LoginView.vue全部

        <template>
          <div class="login-wrap">
            <van-nav-bar :title="flag ? `登录` : `注册`" left-arrow>
              <template #right>
                <van-icon name="ellipsis" size="18" />
              </template>
            </van-nav-bar>
        
            <div class="img-box">
              <img src="../assets/logo.png" alt="" />
            </div>
        
            <van-form @submit="onSubmit()">
              <van-field
                v-model="username"
                name="用户名"
                label="用户名"
                placeholder="用户名"
                :rules="[{ required: true, message: '请填写用户名' }]"
              />
              <van-field
                v-model="password"
                type="password"
                name="密码"
                label="密码"
                placeholder="密码"
                :rules="[{ required: true, message: '请填写密码' }]"
              />
        
              <Verify
                @success="handleAlert('success')"
                @error="handleAlert('error')"
                :type="2"
                :showButton="false"
                fontSize="18px"
                ref="theVerify"
              ></Verify>
        
              <p class="now" @click="handleToggle()">
                {{ flag ? `立即注册` : `已有登录帐号` }}
              </p>
              <div style="margin: 16px">
                <van-button round block type="info" native-type="submit">
                  {{ flag ? `登录` : `注册` }}
                </van-button>
              </div>
            </van-form>
          </div>
        </template>
        
        <script>
        import Verify from "vue2-verify";
        import { Notify } from "vant";
        
        export default {
          components: {
            Verify,
          },
          data() {
            return {
              username: "",
              password: "",
              flag: true,
              verifyFlag: false,
            };
          },
          methods: {
            onSubmit() {
              // console.log(`this.$refs['theVerify']-->`, this.$refs.theVerify);
              // checkCode() 验证; refresh() 重置;
              this.$refs.theVerify.checkCode();
              // this.$refs['theVerify'].refresh()//重置
        
              //验证码不通过
              if (!this.verifyFlag) {
                Notify("验证码出错,请重试");
                this.$refs.theVerify.refresh();
                return;
              }
        
              // 注册
              if (!this.flag) {
                console.log("进行注册");
                this.$api
                  .register(this.username, this.password)
                  .then((value) => {
                    // {"resultCode":200,"message":"SUCCESS","data":null}
                    let { resultCode, message } = value;
                    // console.log(resultCode, message, data);
                    if (resultCode !== 200) {
                      Notify(message || "注册出错,请重试");
                      this.$refs.theVerify.refresh();
                      return;
                    }
        
                    this.username = this.password = ``;
                    Notify({ type: "success", message: "注册成功" });
                    this.$refs.theVerify.refresh();
                    this.flag = true;
                  })
                  .catch((error) => {
                    console.log(`error-->`, error);
                  });
                return;
              }
        
              this.$api
                .login(this.username, this.password)
                .then((value) => {
                  // {"resultCode":200,"message":"SUCCESS","data":"a98cd1e0376b20776dcfb6ff8306031e"}
                  console.log(value);
                  let { resultCode, message, data } = value;
                  if (resultCode !== 200) {
                    Notify(message || "登录出错,请重试");
                    this.$refs.theVerify.refresh();
                    return;
                  }
        
                  this.username = this.password = ``;
                  Notify({ type: "success", message: "登录成功" });
                  if (data) {
                    localStorage.setItem("xfAppToken", data);
                  }
                  this.$router.push("/IndexView");
                })
                .catch((error) => {
                  console.log(`error-->`, error);
                })
                .finally(() => {
                  console.log("登录操作后执行");
                  this.$refs.theVerify.refresh();
                });
              //登录
              // console.log("进行登录");
            },
            handleAlert(text) {
              console.log("handleAlert", text);
              this.verifyFlag = text === "success" ? true : false;
            },
            handleToggle() {
              this.flag = !this.flag;
            },
          },
        };
        </script>
        
        <style lang="less">
        .login-wrap {
          .van-nav-bar .van-icon {
            color: black;
          }
        
          .img-box {
            height: 160px;
            display: flex;
            justify-content: center;
            align-items: center;
        
            img {
            }
          }
        
          .van-button--info {
            background-color: #1baeae;
            border: 1px solid #1baeae;
          }
        
          .now {
            font-size: 14px;
            color: #1995fb;
            margin-left: 15px;
          }
        
          .cerify-code-panel {
            margin-top: 20px;
            margin-left: 15px;
            display: flex;
        
            .verify-code {
              width: 130px !important;
              height: 42px !important;
              line-height: 42px !important;
            }
        
            .verify-code-area {
              display: flex;
        
              .varify-input-code {
                height: 40px;
                line-height: 40px;
                width: 100px;
                margin-left: 10px;
                border: 1px solid #eee;
                font-size: 16px;
                text-indent: 10px;
              }
        
              .verify-change-code {
                font-size: 14px;
              }
            }
          }
        }
        </style>
        
    2. 在二次封装axios的/src/http/http.js中设置请求拦截器的处理。

    3. 在二次封装axios的/src/http/http.js中设置请求拦截器的处理。

    4. 在其它组件的接口随意发起一个axios请求,就会发现请求头上已经有了对应的token。文章来源地址https://www.toymoban.com/news/detail-429490.html

进阶参考

  1. 你不知道的Web Components现状 – 2022年对Web Components框架的解释

到了这里,关于20230428----重返学习-vue项目的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 20230406----重返学习-AJAX

    AJAX全称async javascript and xml。 以前的数据一般是xml,现在大多是json。 AJAX不是一种新的技术,而一个与后端通信的方式。 特色: 异步获取数据,局部更新页面。 数据渲染 服务器渲染 客户端渲染----(局部更新页面) 服务器渲染 [外链图片转存失败,源站可能有防盗链机制,建议将图

    2023年04月10日
    浏览(24)
  • 20230602----重返学习-React路由

    新版的是react-router-dom是6版本,而旧版的是5版本。 基于前端路由实现SPA单页面应用,其核心在于:构建路由表(构建路由匹配机制)。 每一次 路由切换 (包含 刚开始第一次渲染页面 ),都会拿 当前的地址 (或者 哈希值 )去路由表中进行查找匹配,找到相匹配的组件。 包含

    2024年02月07日
    浏览(24)
  • 20230712----重返学习-权限校验

    无权限直接移除需权限校验的视图v-if版 登录时拿到用户所有的权限标识列表并保存到vuex中。 v-if中判断vuex中权限标识列表是否包含有当前v-if对应按钮或视图的权限标识,没有就直接移除。 无权限直接移除需权限校验的视图-自定义指令版 登录时拿到用户所有的权限标识列表

    2024年02月15日
    浏览(25)
  • 20230620----重返学习-移动端事件处理-响应式

    移动端的事件处理 移动端事件处理 PC端主要以: 鼠标事件 、 键盘事件 、 资源加载事件 、 动画事件 等事件为主。 其中 click 在 PC端 是 点击事件 ! 移动端主要以: 手指事件 ( 单手指 和 多手指 )、 资源加载事件 、 动画事件 等为主。 其中, click 在 移动端 是 单击事件

    2024年02月09日
    浏览(29)
  • 20230401----重返学习-冒泡相关事件-拖拽-放大镜

    mouseenter/mouseleave与mouseover/mouseout mouseover/mouseout 有冒泡,忽略层级之间的关系 mouseenter/mouseleave 没冒泡,不会忽略层级之间的关系 事件委托 事件委托: 也叫事件代理,将绑定的事件委托给祖先元素,祖先元素监听事件,并利用e.target来分配给当前元素 原理是: 事件冒泡机制 事

    2023年04月08日
    浏览(29)
  • 20230728----重返学习-跨域-模块化-webpack初步

    跨域 为什么要跨域? 浏览器为了安全,不能让我们的html文件可以随意引用别的服务器中的文件,只允许我们的html或js文件中,请求我们自己服务器。这个就是浏览器的同源策略。 因为我们的网页是一个html文件,这个html是在一个域名里的。而这个html会引用各种文件,如图片

    2024年02月15日
    浏览(35)
  • 20230711----重返学习-组件缓存-图片上传-富文编辑器-鉴权处理

    keep-alive组件的使用 keep-alive组件的原理 图片上传流程 点击上传图片后,把图片发送给服务器。 服务器返回一个相对或绝对地址。 提交时,把图片地址与其余表单数据一起传递给服务器。 el-upload组件 图片上传分为两步: 选取图片 规则限制:类型、大小… multiple 是否支持多

    2024年02月16日
    浏览(37)
  • 20230619----重返学习-图片缩略图幻灯片-插件封装的步骤-NativeApp与WebApp

    总体思路 整理思路。 所有的结构都包在一个盒子中。盒子里有两层内容: 盒子宽高由前端根据设计稿来定。 盒子宽高应具体到px,以便内部使用百分比进行布局。 一层是封面,用于展示播放时长和视频主图。 一层是进度图,用于展示进度条对应的视频缩略图。根据用户鼠

    2024年02月10日
    浏览(34)
  • 20230707----重返学习-物美管理系统-登录流程-页面路由跳转-面包屑导航-访问历史列表

    登录流程 客户端: 表单校验。 避免无效请求。 防止SQL注入。 密码进行加密-MD。 非对称性加密。 获取表单信息,向服务器发送。 请求-post。 服务器端: 获取请求主体传递的信息-建议二次校验。 根据传递的验证码及uuid,到数据库去查询,校验验证码的准确性。 不准确:反

    2024年02月13日
    浏览(34)
  • 20230529----重返学习-复合组件通信redux-redux源码-redux工程化开发-自定义hook

    要想实现复合组件通信,一般采用公共状态管理方案。 常见的公共状态管理方案: 官方推荐的:redux。 redux + react-redux + redux-logger / redux-promise / redux-saga / redux-thunk :中间件。 代表:dva「redux-saga 」或 umi。 @reduxjs/toolkit :工具类。 mobx 。 zustand 。 … redux的应用场景 redux 在以

    2024年02月06日
    浏览(36)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包