当前位置 : 主页 > 网络编程 > JavaScript >

关于VueRouter导入的全过程

来源:互联网 收集:自由互联 发布时间:2023-02-08
目录 router nanoid的使用 引入 使用 路由 1-1 安装依赖 1-2 引入 1-3 在main.js中使用 1-4 App.vue 全局过滤器 element-ui 全局组件 Vuc-cli中的视配 1-1 安装依赖 1-2 配置文件 1-3 main.js 1-4 public/index.ht
目录
  • router
    • nanoid的使用
    • 引入
    • 使用
  • 路由
    • 1-1 安装依赖
    • 1-2 引入
    • 1-3 在main.js中使用
    • 1-4 App.vue
  • 全局过滤器
    • element-ui
      • 全局组件
        • Vuc-cli中的视配
          • 1-1 安装依赖
          • 1-2 配置文件
          • 1-3 main.js
          • 1-4 public/index.html
          • 1-5 在pc端视配
        • slot封装动画
          • 项目初始化
            • 1-1 .router-link-active
            • 1-2 动态显示tabbar
            • 1-3 跳转回前一个页面
            • 1-4轮播
          • vant ui的按需导入
            • 1-1 安装依赖
            • 1-2 配置babel.config.js
            • 1-3 配置main.js
          • 嵌套路由
            • 1-1 router.js
            • 1-2 index.vue
          • 异步路由​
            • 页面跳转和生命周期
              • 页面跳转
            • DOM和生命周期
              • 缓存的进一步封装
                • axios
                  • 跨域
                  • 地址值的放置
                • Vuex
                  • 1、state
                  • 2、mutation
                  • 3、actions
                • keep-alive
                  • 路由守卫
                    • Login_guard(Vue&koa)
                      • 一、登录页面
                      • 二、后台代码
                      • 三、配置cookie跨域访问
                    • 懒加载
                      • 1、图片懒加载
                      • 2、axios拦截器
                      • 3、上拉刷新
                      • 4、路由滚动记录当前滚动条位置问题​
                    • Vue路由跳转的bug

                      router

                      nanoid的使用

                      ​ --生成随机id

                      引入

                      yarn add nanoid

                      使用

                      import {nanoid} from 'nanoid'
                      var id = nanoid()

                      路由

                      1-1 安装依赖

                      yarn add vue-router

                      1-2 引入

                      router/index.js 

                      import Vue from 'vue'
                      import VueRouter from 'vue-router'
                      Vue.use(VueRouter)
                      import Movie from '../pages/Movie/index.vue'
                      import Music from '../pages/Music/index.vue'
                      const routes = [
                        {
                          path:"/music",
                          component:Music
                        },
                        {
                          path:"/movie",
                          component:Movie
                        }
                      ]
                      const router = new VueRouter({
                        routes,
                        mode:"history"
                      })
                      export default router;
                      

                      1-3 在main.js中使用

                      import Vue from 'vue'
                      import App from './App.vue'
                      import router from './router'
                      Vue.config.productionTip = false
                      new Vue({
                        router,
                        render: h => h(App),
                      }).$mount('#app')

                      1-4 App.vue

                      <template>
                        <div>
                          <router-view></router-view>
                        </div>
                      </template>

                      全局过滤器

                      在main.js中挂载在Vue原型上

                      Vue.filter("handleStr",function(val){
                        if(val.length > 3){
                          val = val.slice(0,3) + '...'
                        }
                        return val
                      })
                      

                      element-ui

                      安装依赖

                      yarn add element-ui

                      main.js

                      ....
                      import ElementUI from 'element-ui';
                      import 'element-ui/lib/theme-chalk/index.css';
                      Vue.use(ElementUI);
                      ...

                      全局组件

                      import Loading from '../components/Loading.vue'
                      Vue.component("Loading",Loading)

                      Vuc-cli中的视配

                      只在手机端

                      lib-flexible 阿里

                      1-1 安装依赖

                      yarn add lib-flexible postcss-pxtorem@5.1.1

                      1-2 配置文件

                      新建postcss.config.js

                      module.exports = {
                        plugins: {
                          'postcss-pxtorem': {
                            rootValue: 75,
                            propList: ['*'],
                          },
                        },
                      };

                      1-3 main.js

                      导入lib-flexible

                      import 'lib-flexible/flexible.js'

                      1-4 public/index.html

                      将此行注释,关闭视口

                      <meta name="viewport" content="width=device-width,initial-scale=1.0">
                      

                      1-5 在pc端视配

                      <template>
                        <div id="app">
                          ...
                        </div>
                      </template>
                      <script>
                          ...
                      </script>
                      <style>
                      *{
                        margin: 0;
                        padding: 0;
                      }
                      #app{
                        width: 10rem;
                        margin: 0 auto;
                        background-color: red;
                      }
                      </style>

                      slot封装动画

                      // #1 定义一个组件
                      <template>
                        <transition>
                          <slot name="fade"></slot>
                        </transition>
                      </template>
                      <script>
                      export default {
                      }
                      </script>
                      <style>
                      .v-enter,.v-leave-to{
                        opacity: 0;
                      }
                      .v-enter-active,.v-leave-active{
                        transition: opacity 4s;
                      }
                      </style>
                      // #2 使用
                      <template>
                        <div class="about">
                          <Fade>
                            <h1 slot="fade" v-show="isShow">This is an about page</h1>
                          </Fade>
                        </div>
                      </template>
                      <script>
                      import Fade from '../components/Fade.vue'
                      export default {
                        data() {
                          return {
                            isShow:true
                          }
                        },
                        components:{
                          Fade
                        }
                      }
                      </script>

                      项目初始化

                      1、rem
                      2、asssreset.css

                      1-1 .router-link-active

                      被选中的路由样式

                      .router-link-active{
                          color: #ff2d51;
                        }

                      1-2 动态显示tabbar

                      ​ – 在路由配置中增加一条meta属性

                      const routes = [
                        {
                          path: '/films',
                          name: 'Films',
                          component:Films,
                          meta:{
                            isNav:true
                          }
                        },
                        {
                          path: '/article',
                          name: 'Article',
                          component:Article,
                          meta:{
                            isNav:true
                          }
                        },
                        {
                          path: '/center',
                          name: 'Center',
                          component:Center,
                          meta:{
                            isNav:true
                          }
                        },
                        {
                          path:"/movie/:id",
                          name:'MovieDetail',
                          component:MovieDetail
                        }
                      ]

                      通过v-if动态显示

                      <tab-bar v-if="this.$route.meta.isNav"></tab-bar>

                      1-3 跳转回前一个页面

                      this.$router.back()

                      1-4轮播

                      yarn add vue-preview
                      
                      import VuePreview from 'vue-preview'
                      Vue.use(VuePreview)

                      vant ui的按需导入

                      1-1 安装依赖

                      yarn add vant babel-plugin-import

                      1-2 配置babel.config.js

                      module.exports = {
                        presets: [
                          '@vue/cli-plugin-babel/preset'
                        ],
                        plugins: [
                          ["import", {
                            "libraryName": "vant",
                            "libraryDirectory": "es",
                            "style": true
                          }]
                        ]
                      }

                      1-3 配置main.js

                      import {Button} from 'vant'
                      Vue.use(Button)
                      

                      router-view实现动画

                      <template>
                        <div>
                          <div class="cover" v-if="isShow"></div>
                          <transition 
                            @before-enter="handleBeforeEnter"
                            @enter="handleEnter"
                          >
                            <slot></slot>
                          </transition>
                        </div>
                      </template>
                      <script>
                      /* 
                      .v-enter              @before-enter
                      .v-ernter-active      @enter
                      .v-enter-to           @after-enter
                      */
                        export default {
                          data() {
                            return {
                              isShow:false
                            }
                          },
                          methods:{
                            handleBeforeEnter(){
                              this.isShow = true
                            },
                            handleEnter(){
                              setTimeout(() => {
                                this.isShow = false
                              }, 200);
                            }
                          }
                        }
                      </script>
                      <style>
                        .v-enter-active{
                          animation: animate 2s linear;
                        }
                        @keyframes animate {
                          0%{
                            opacity: 0;
                            transform: translateY(0px);
                          }
                          50%{
                            opacity: .5;
                            transform: translateY(20px);
                          }
                          100%{
                            opacity: 1;
                            transform: translateY(0px);
                          }
                        }
                        .cover{
                          width: 100%;
                          height: 100%;
                          background-color: #fff;
                          position: fixed;
                          z-index: 10;
                        }
                      </style>

                      嵌套路由

                      1-1 router.js

                       {
                          path: '/films',
                          name: 'Films',
                          component:Films,
                          meta:{
                            isNav:true
                          },
                          children:[
                            {
                              path:"nowPlaying",
                              component:NowPlaying
                            }
                          ]
                        },

                      1-2 index.vue

                      需要加入router-view

                      <template>
                          ...
                          <div class="container">
                              <!-- 装载父路由下的子路由的对应 -->
                              <router-view></router-view>
                          </div>
                      </template>

                      异步路由​

                      --又称路由懒加载

                      {
                          path: '/about',
                          name: 'About',
                          // 异步路由
                          component: () => import(/* webpackChunkName: "about" */ '../views/About.vue')
                      },

                      怎么减少首屏渲染时间

                      1、使用异步路由 

                      页面跳转和生命周期

                      ​ --面试常客

                      页面跳转

                      1-1 A页面初次加载

                      beforeCreate(){
                          console.log('beforeCreate');
                      },
                      created(){
                          console.log('created');
                      },
                      beforeMount(){
                          console.log('beforeMount');
                      },
                      mounted(){
                          console.log('mounted');
                      },

                      1-2 A->B

                      从A页面跳转到B页面

                      A页面触发以下生命周期

                      beforeDestroy(){
                          console.log('beforeDestroy');
                      },
                      destroyed(){
                          console.log('destroyed');
                      }

                      1-3 B–>A

                      从B页面回到A页面

                      A页面触发以下生命周期

                      beforeCreate(){
                          console.log('beforeCreate');
                      },
                      created(){
                          console.log('created');
                      },
                      beforeMount(){
                          console.log('beforeMount');
                      },
                      mounted(){
                          console.log('mounted');
                      },

                      upDate

                      beforeUpdate , beforeUpdate执行需要满足以下两个条件

                      1、data中的数据更新的时候

                      2、模板中要使用data中的数据

                      destroyed

                      # A页面 --> b页面

                      b页面执行以下生命周期:

                      • 1.beforeCreate        B
                      • 2.created            B
                      • 3.beforeMount        B
                      • 4.beforeDestroy        A
                      • 5.destroyed            A
                      • 6.mounted            B

                      DOM和生命周期

                      只能在mounted生命周期中获取DOM

                      缓存的进一步封装

                      localStorage.setItem() 函数会将对象或者数组全部转换成字符串的形式

                      所以可以对缓存进行判断,使用 JSON.stringify 和 JSON.parse 分别处理数据

                      const setLocalStorage = (key , value) => {
                        if(value instanceof Array || value instanceof Object){
                          value = JSON.stringify(value)
                        }
                        localStorage.setItem(key , value)
                      }
                      const getLocalStorage = (key) =>{
                        var val = localStorage.getItem(key)
                        var reg = /^[[{].*[\]}]/
                        if(reg.test(val)){
                          val = JSON.parse(val)
                        }
                        return val
                      }

                      axios

                      跨域

                      安装依赖

                      yarn add axios-jsonp

                      axios格式

                      import axios from 'axios'
                      import jsonpAdapter from 'axios-jsonp'
                      axios({
                          url:"",
                          adapter: jsonpAdapter,
                      }).then(
                          res => console.log(res)
                      )

                      腾讯地图api需要在最后加上 &output=jsonp

                      https://apis.map.qq.com/ws/location/v1/ip?key=L6UBZ-JSLCU-FRAVA-4DBQG-V5WC5-2RBJ4&output=jsonp

                      地址值的放置

                      http://47.108.197.28:3000/top/playlist?limit=1&offset=1

                      在小程序中

                      wx.request({
                      })

                      axios中

                      import axios from 'axios'
                      axios({
                          url:"http://47.108.197.28:3000/top/playlist",
                          method:"get",
                          params:{
                          limit:1
                          }
                      }).then(res=>{
                          console.log(res)
                      })

                      Vuex

                      import Vue from 'vue'
                      import Vuex from 'vuex'
                      Vue.use(Vuex)
                      export default new Vuex.Store({
                        state: {
                        },
                        mutations: {
                        },
                        actions: {
                        },
                        modules: {
                        }
                      })

                      1、state

                      ​ --state中存放的是数据

                      state: {
                          num:10
                      }
                      this.$store.state

                      2、mutation

                      ​ --mutation中的函数第一个默认参数是state

                      ​ --连接方式 commit

                      mutations: {
                          add(state){
                              console.log(state);
                              state.num++;
                          }
                      },
                      this.$store.commit('add')

                      3、actions

                      ​ --actions中的函数第一个默认值是上下文

                      ​ --连接方式 dispatch

                      actions: {
                          addNum(ctx){
                              console.log(ctx);
                              ctx.commit("add")
                          }
                      },
                      this.$store.dispatch('a')

                      keep-alive

                      • 使用keep-alive之后,路由切换的时候,生命周期函数不会重复的触发
                      • 组件不会被销毁,而是被缓存起来。当加载到对应的路由页面,缓存的组件会被加载

                      路由组件的两个生命周期函数

                      /* 路由组件被激活时触发。 */
                      activated(){
                          console.log('activated')
                      }
                      /* 路由组件失活时触发。 */
                      deactivated(){
                          console.log('deactivated')
                      }

                      路由守卫

                      全局路由守卫

                      router.beforeEach((to , from ,next)=>{
                        console.log(to);    // 要跳转的路由
                        console.log(from);  // 起点路由
                        next();
                      })

                      Login_guard(Vue&koa)

                      一、登录页面

                      <template>
                        <div>
                          <el-form
                            :model="ruleForm"
                            status-icon
                            :rules="rules"
                            ref="ruleForm"
                            label-width="100px"
                            class="demo-ruleForm"
                          >
                          <!-- props为了规则校验 rules -->
                          <el-form-item label="用户名" prop="username">
                              <el-input  type="text" v-model.number="ruleForm.username"></el-input>
                            </el-form-item>
                            <el-form-item label="密码" prop="pass">
                              <el-input
                                type="password"
                                v-model="ruleForm.pass"
                                autocomplete="off"
                              ></el-input>
                            </el-form-item>
                            <el-form-item label="确认密码" prop="checkPass">
                              <el-input
                                type="password"
                                v-model="ruleForm.checkPass"
                                autocomplete="off"
                              ></el-input>
                            </el-form-item>
                            <el-form-item>
                              <el-button type="primary" @click="submitForm('ruleForm')"
                                >提交</el-button
                              >
                              <el-button @click="resetForm('ruleForm')">重置</el-button>
                            </el-form-item>
                          </el-form>
                        </div>
                      </template>
                      <script>
                      export default {
                        // beforeRouteEnter () {
                        //   /* 在局部守卫中获取不到this */
                        //   console.log(1);
                        // },
                        data() {
                          var checkUsername = (rule, value, callback) => {
                            if (!value) {
                              return callback(new Error("用户名不能为空"));
                            }else{
                              callback();
                            }
                          };
                          var validatePass = (rule, value, callback) => {
                            if (value === "") {
                              callback(new Error("请输入密码"));
                            } else {
                              if (this.ruleForm.checkPass !== "") {
                                this.$refs.ruleForm.validateField("checkPass");
                              }
                              callback();
                            }
                          };
                          var validatePass2 = (rule, value, callback) => {
                            if (value === "") {
                              callback(new Error("请再次输入密码"));
                            } else if (value !== this.ruleForm.pass) {
                              callback(new Error("两次输入密码不一致!"));
                            } else {
                              callback();
                            }
                          };
                          return {
                            ruleForm: {
                              pass: "",
                              checkPass: "",
                              username: "",
                            },
                            rules: {
                              pass: [{ validator: validatePass, trigger: "blur" }],
                              checkPass: [{ validator: validatePass2, trigger: "blur" }],
                              username: [{ validator: checkUsername, trigger: "blur" }],
                            },
                          };
                        },
                        methods: {
                          submitForm(formName) {
                            this.$refs[formName].validate((valid) => {
                              if (valid) {
                                // alert("submit!");
                                // console.log(this.ruleForm);
                                // console.log(username,pass);
                                /* 发送http请求 */
                                this.loginHttp()
                              } else {
                                console.log("error submit!!");
                                return false;
                              }
                            });
                          },
                          resetForm(formName) {
                            this.$refs[formName].resetFields();
                          },
                          loginHttp(){
                            var {username , pass} = this.ruleForm
                            this.$http({
                              method: 'post',
                              url:'http://localhost:8000/login',
                              data:{
                                username,
                                pass
                              }
                            }).then(res=>{
                              console.log(res.data);
                              if(res.data.code == 200){
                                this.$message({
                                  message:res.data.msg,
                                  type:"success",
                                  duration:1000
                                })
                                this.$router.push('/home')
                              }else{
                                this.$message({
                                  message:res.data.msg,
                                  type:"warning",
                                  duration:1000
                                })
                              }
                            })
                          }
                        }
                       
                      };
                      </script>

                      二、后台代码

                      const koa = require("koa");
                      const app =  new koa();
                      const koaBody = require("koa-body");
                      const router = require("koa-router")();
                      const cors = require("koa2-cors");
                       
                          /* username=cheng  pass=123456 */
                          console.log(ctx.request.body);
                          var {username , pass } = ctx.request.body
                          if(username == "cheng" && pass == "123456"){
                            ctx.cookies.set("loginAuth",true,{
                              /* httpOnly:false   设置前端可读 */
                              httpOnly:false
                            })
                            ctx.body = {
                              code:200,
                              msg:"登录成功"
                            }
                          }else{
                            ctx.body = {
                              code:400,
                              msg:"登录失败,用户名或密码错误"
                            }
                          }
                      })
                      /* 后端配置cookie可以实现跨域访问 */
                      app.use(cors({
                        origin:ctx =>{
                          return ctx.headers.origin
                        },
                        credentials:true
                      }));
                      app.use(koaBody());
                      app.use(router.routes());
                      app.listen(8000);

                      三、配置cookie跨域访问

                      3-1 配置后端cookie可以访问

                      /* 后端配置cookie可以实现跨域访问 */
                      app.use(cors({
                        origin:ctx =>{
                          return ctx.headers.origin
                        },
                        credentials:true
                      }));

                      3-2 配置前端跨域访问cookie

                      import axios from 'axios'
                      /* 设置前端跨域访问cookie */
                      axios.defaults.withCredentials = true
                      axios.defaults.crossDomain = true

                      3-3 vue上获取cookie

                      安装依赖

                      yarn add vue-cookie

                      配置main.js

                      import VueCookie from 'vue-cookie'
                      Vue.use(VueCookie)

                      在页面中获取cookie

                      mounted() {
                          console.log(this.$cookie.get('loginAuth'));
                      }

                      3-4 路由守卫

                      ​ --没有登录的情况下,不能进入其它页面

                      ​ --已经登录的情况下,直接进入首页

                      var vm = new Vue();
                      router.beforeEach((to,from,next)=>{
                        console.log(vm.$cookie.get('loginAuth'));
                        var isLogin = vm.$cookie.get('loginAuth')
                        if(to.path == "/login"){
                          /* 1、登录页面,如果cookie显示登录了直接进入home页面,如果没有登录,正产执行login页的逻辑 */
                          if(isLogin){
                            router.push('/home')
                          }else{
                            next()
                          }
                        }else{
                          /* 2、在其他页面,如果登录正常显示,没有登录则停留在login页面 */
                          if(isLogin){
                            next()
                          }else{
                            router.push('/login')
                          }
                        }
                      })

                      懒加载

                      1、图片懒加载

                      安装依赖

                      yarn add vue-lazyload

                      在main.js中进行配置

                      import VueLazyLoad from 'vue-lazyload'
                      Vue.use(VueLazyLoad,{
                        preLoad:1.3,
                        loading:require('@/assets/loading.gif')
                      })

                      使用(将:src替换成v-lazy)

                      <template>
                        <div class="home">
                          <div  v-for="item of playlists" :key="item.id">
                            <img  class="item" v-lazy="item.coverImgUrl" alt="">
                            <p>{{item.name}}</p>
                          </div>
                        </div>
                      </template>

                      2、axios拦截器

                      ​ --实现loading的加载效果

                      在vuex中定义一条isShowLoading     -->    设置加载条是否显示

                      export default new Vuex.Store({
                        state: {
                          isSowLoading:true
                        },
                      })

                      main.js

                      // 配置 请求拦截 和 响应拦截
                      // 添加请求拦截器
                      axios.interceptors.request.use(function (config) {
                        // 在发送请求之前做些什么
                        store.state.isSowLoading = true
                        return config;
                      });
                      // 添加响应拦截器
                      axios.interceptors.response.use(function (response) {
                        // 2xx 范围内的状态码都会触发该函数。
                        // 对响应数据做点什么
                        store.state.isSowLoading = false
                        return response;
                      });

                      App.vue设置loading

                      <template>
                        <div id="app">
                          <Loading v-if="this.$store.state.isShowLoading"/>
                          <router-view/>
                        </div>
                      </template>

                      3、上拉刷新

                      vant-ui 中整合了小程序中的 onBottom 和 onLoad

                      <template>
                        <div class="home">
                          <van-list
                            class="home"
                            v-model="loading"
                            :finished="finished"
                            finished-text="没有更多了"
                            @load="onLoad"
                          >
                            <van-cell @click="handleClick(item.id)" v-for="item of playlists" :key="item.id">
                              <img class="item" v-lazy="item.coverImgUrl" alt="">
                              <p>{{item.name}}</p>
                            </van-cell>
                          </van-list>
                        </div>
                      </template>
                      <script>
                      export default {
                        name: 'Home',
                        data() {
                          return {
                            playlists:[],
                            loading:false,
                            finished:false
                          }
                        },
                        mounted() {
                          
                        },
                        methods: {
                          onLoad(){
                            setTimeout(()=>{
                              var offset = this.playlists.length
                              console.log(1);
                              this.axios.get(`http://47.108.197.28:3000/top/playlist?offset=${offset}&limit=20`).then(res =>{
                                var playlists = this.playlists.concat(res.data.playlists)
                                this.playlists = playlists
                                this.loading = false
                              })
                            },500)
                          },
                          handleClick(id){
                            this.$router.push(`detail?id=${id}`)
                          }
                        },
                      }
                      </script>
                      <style scoped>
                        .item{
                          width: 150px;
                          height: 150px;
                        }
                        .home{
                          display: flex;
                          justify-content: space-between;
                          flex-wrap: wrap;
                        }
                        .van-cell{
                          width: 150px;
                        }
                        .home >>> .van-list__loading{
                          position: fixed;
                          bottom: 0;
                          left: 50%;
                          transform:translateX(-50%);
                        }
                      </style>

                      4、路由滚动记录当前滚动条位置问题​

                      在路由设置中,重置滚动条的x,y

                      const router = new VueRouter({
                        ...
                        scrollBehavior (to , from , savedPosition) {
                          if( to.path == "/detail"){
                            return {x:0,y:0}    // 让页面出于顶部
                          }else{
                            return savedPosition    // 让页面出于记录点
                          }
                        }
                      })

                      Vue路由跳转的bug

                      项目中遇到如下报错内容:

                      Uncaught (in promise) Error: Redirected when going from “/XXX” to “/XXX” via a navigation guard.

                      原因:vue-路由版本更新产生的问题,导致路由跳转失败抛出该错误,但并不影响程序功能

                      在main.js中改变push原型

                      import Router from 'vue-router'
                      const originalPush = Router.prototype.push
                      Router.prototype.push = function push(location, onResolve, onReject) {
                        if (onResolve || onReject) return originalPush.call(this, location, onResolve, onReject)
                        return originalPush.call(this, location).catch(err => err)
                      }

                      以上为个人经验,希望能给大家一个参考,也希望大家多多支持易盾网络。

                      上一篇:vite前端构建Turborepo高性能monorepo方案
                      下一篇:没有了
                      网友评论