vue vue-router 第一次加载页面 ,页面切换很慢 是怎么回事?,后面切换正常

clipboard.png

vue-router
import Vue from 'vue'
import VueRouter from 'vue-router'
Vue.use(VueRouter)
const router = new VueRouter({
mode: 'hash',
base: __dirname,
linkActiveClass: 'active',
routes:[

{
  path:'',
  component: resolve => void(require(['@/view/Helping.vue'],resolve)),// 懒加载
  meta: {
    title: '帮扶中',
  },
},
{
  path:'/help',
  component: resolve => void(require(['@/view/Help.vue'],resolve)),// 懒加载
  meta: {
    title: '已帮扶',
  },
},
{
  path:'/consult',
  name:'consult',
  component: resolve => void(require(['@/view/Consult.vue'],resolve)),// 懒加载
  meta: {
    title: '咨询帮助',
  },
},
{
  path:'/form',
  name:'form',
  component: resolve => void(require(['@/view/Form.vue'],resolve)),// 懒加载
  meta: {
    title: '志愿者服务报名表',
  },
},
{
  path:'/mp/:type',
  name:'mp',
  component: resolve => void(require(['@/view/Mp.vue'],resolve)),// 懒加载
  meta: {
    title: '幺婶新闻列表',
  },
},
{
  path:'/detail/:id/:routType',
  name : 'detail',
  component: resolve => void(require(['@/view/Detail.vue'],resolve)),// 懒加载
  meta: {
    title: '详情',
  },
},
{
  path:'/mpDetail/:id',
  name : 'mpDetail',
  component: resolve => void(require(['@/view/MpDetail.vue'],resolve)),// 懒加载
  meta: {
    title: 'mp详情',
  },
},
{
  path:'/volSystem',
  name : 'volSystem',
  component: resolve => void(require(['@/view/VolSystem.vue'],resolve)),// 懒加载
  meta: {
    title: '“幺婶热线”志愿者准入制度',
  },
},
{
  path:'/manage',
  name : 'manage',
  component: resolve => void(require(['@/view/Manage.vue'],resolve)),// 懒加载
  meta: {
    title: '“幺婶热线”志愿服务积分管理办法',
  },
},
{
  path:'/login',
  name : 'login',
  component: resolve => void(require(['@/view/Login.vue'],resolve)),// 懒加载
  meta: {
    title: '“幺婶热线”志愿者登录',
  },
},
{
  path:'*',
  component: resolve => void(require(['@/view/404.vue'],resolve)),// 懒加载
  meta: {
    title: '404',
  },
}

]
})

router.afterEach((route) => {
document.title = 幺婶在线-${route.meta.title};
});

// 保存滚动条原来的位置
router.beforeEach((to, from, next) => {
from.meta.savedPosition = document.body.scrollTop || document.documentElement.scrollTop
next()
})
router.afterEach((to, from) => {
let flag = to.path.includes('detail') ||

         from.path.includes('detail')

let time = flag ? 0 : 80;
scroll(to, from, time)
})
function scroll (to, from, time) {
if (to.meta.savedPosition) {

let fg = to.path.includes('detail')

if (fg) to.meta.savedPosition = 0;
setTimeout(() => {
  window.scrollTo(0, to.meta.savedPosition)
}, time)

} else {

setTimeout(() => {
  window.scrollTo(0, 0)
}, time)

}
}

/*router.beforeEach((to, from, next) => {
if (to.matched.some(record => record.meta.requiresAuth)) {

const auth = store.state.account.auth;
// this route requires auth, check if logged in
// if not, redirect to login page.
if (!auth.check()) {
  next({
    path: '/account/login',
    query: { redirect_url: to.fullPath },
  });
  return;
}

}
next();
});*/

export default router;

/**

  • fix ios title刷新不了的bug
  • @iframeLoad
  • @author hiluluke
    */

/*const iframeLoad = function (src) {
let iframe = document.createElement('iframe')
iframe.style.display = 'none'
iframe.src = src
document.body.appendChild(iframe)
iframe.addEventListener('load', function () {

setTimeout(function () {
  iframe.remove()
}, 0)

})
}*/
/*// document title change
Router.afterEach((transition) => {
document.title = transition.to.title || 'CNode.js'
if (navigator.userAgent.match(/(i1+;( U;)? CPU.+Mac OS X/)) {

let src = '/static/fixrouter.html?' + Math.random()
iframeLoad(src)

}
});*/

//==============================app.vue===========================================

<template>
<div class="joykit-app xh-background-fff">

<transition :name="page">
  <keep-alive>
    <router-view class="container"></router-view>
  </keep-alive>
</transition>

</div>
</template>
<script>

export default {

data () {
  return {
    page: ''
  }
},
methods: {

},
mounted() {

},
computed:{

},
watch: {
  $route (to, from) {
    var fg =  to.path.includes('detail') ||
              to.path.includes('mpDetail') ||
              to.path.includes('volSystem') ||
              to.path.includes('manage')
    var lg =  from.path.includes('detail') ||
              from.path.includes('mpDetail') ||
              from.path.includes('volSystem') ||
              from.path.includes('manage')
    if ( fg) {
      this.page = 'content-right'
    } else if (lg ) {
      this.page = 'content-left'
    }else{
      this.page = ''
    }
  }
},
components: {

},

}
</script>
<style lang="scss">
@import '../assets/style/transition.scss';
</style>

//==============================footer.vue===========================================
<template>
<div class="footer">

<ul layout="row center-stretch">
  <li v-if="$route.name !='detail' &&
           $route.name !='form'   &&
           $route.name !='mp'     &&
           $route.name !='mpDetail'"
      v-for="(item, index) in items">
    <router-link :to="item.url">
      <span>{{item.text}}</span>
    </router-link>
  </li>
</ul>

</div>
</template>

<script>
export default {

now: 0,
drop: false,
data () {
  return {
    items:[
      {
        url  : '/',
        text : '帮扶中'
      },
      {
        url  : '/help',
        text : '已帮扶'
      },
      {
        url  : '/consult',
        text : '咨询帮助'
      }
    ]
  }
},
methods: {
},
computed: {
},
watch:{
},
components: {
}

}
</script>

<style lang="scss" scoped>

.footer{

width: 100%;
position: fixed;
bottom: 0;
left:0;
z-index: 99;
background-color: #f5f5f5;
border-top: 1px solid #CCCCCC;
ul{
  background-color:#FAFAFA;
  li {
    text-align: center;
    position:relative;
    a {
      display: block;
      font-size: .3rem;
      padding: .3rem .15rem;
      span{color: #666}
    }
    a.router-link-exact-active{
      background-color: #EAEAEA;
    }
  }
li:after{
  content: " ";
  position: absolute;
  right: 0;
  top: 0;
  width: 1px;
  bottom: 0;
  border-right: 1px solid #CCCCCC;
  color: #CCCCCC;
  -webkit-transform-origin: 100% 0;
  transform-origin: 100% 0;
  -webkit-transform: scaleX(0.5);
  transform: scaleX(0.5);
}
li:last-of-type:after{
  border-right: none;
}
}

}
</style>

//==============================首页.vue===========================================

<template>
<div class="package">

<v_header></v_header>
<v_subjectTop :text='"问政热点"' :left_show="true" :right_show="true" :pos_right="true"></v_subjectTop>
<div id="helpWrapper">
  <div id='helpScroller'>
    <v_list :prop_type="'2'"></v_list>
  </div>
</div>
<v_footer></v_footer>

</div>
</template>
<script>
import v_header from '../components/header.vue'
import v_subjectTop from '../components/subjectTop.vue'
import v_list from '../components/list.vue'
import v_footer from '../components/footer.vue'
export default {

data () {
  return {
    alloyTouch:{},
  }
},
mounted() {
  var self=this;
  var alloy = {};
  alloy.scroller = document.getElementById("helpScroller");
  alloy.loading = false;
  Transform(alloy.scroller, true);
  self.alloyTouch = new AlloyTouch({
    touch: "#helpWrapper",
    vertical: true,
    target: alloy.scroller,
    property: "translateY",
    maxSpeed: 2,
    outFactor: 0.2,
    min: 160 * -20 + window.innerHeight - 202 - 50,
    max: 0,
    touchStart: function () {
      self.reastMin(alloy,self.alloyTouch);
    },
    lockDirection: false,
    change: function (v) {
      self.alloyTouchChange(v,alloy,self.alloyTouch);
    }
  });
  document.addEventListener("touchmove", function (evt) {
    evt.preventDefault();
  }, false);
},
methods: {
  alloyTouchChange(v,alloy,alloyTouch){
    var self = this;
    if (v <= alloyTouch.min + 5 && !alloy.loading) {
      alloy.loading = true;
      self.loadMore(alloy,alloyTouch);
    }
    if (v < 0) {
      if (v < -140) v = -140;
      var scale = (240 + v) / 240;
    } else {
      var scale = 1 + v / 240;
    }
  },
  loadMore(alloy,alloyTouch) {
    var self = this;
    setTimeout(function () {
      //self.$store.dispatch('actDefaultNewsList');
      alloy.loading = false;
      self.reastMin(alloy,alloyTouch);
    }, 500)
  },
  reastMin(alloy,alloyTouch) {
    // let loadHeight = parseInt(getComputedStyle(alloy.load).height);
    let scrollHeight = parseInt(getComputedStyle(alloy.scroller).height);
    alloyTouch.min = -1 * scrollHeight + window.innerHeight ;
  }
},
computed: {
},
components: {
  v_header,v_subjectTop,v_list,v_footer
}

}
</script>
<style lang="scss" scoped>

</style>
<style lang="scss" scoped>
#helpScroller, #helpWrapper {

position: absolute;
width: 100%;

}

#helpWrapper, body {

overflow: hidden;

}

#helpWrapper {

z-index: 1;
top: 0;
bottom: 0;
left: 0;

}

#helpScroller {

padding-top: 2.55rem;
z-index: 1;
-webkit-tap-highlight-color: rgba(0,0,0,0);
will-change: transform;
-webkit-transform: translateZ(0);
transform: translateZ(0);
-webkit-touch-callout: none;
-webkit-user-select: none;
user-select: none;
-webkit-text-size-adjust: none;
text-size-adjust: none;
-webkit-perspective: 1000;
-webkit-backface-visibility: hidden;
backface-visibility: hidden;

}
</style>

//==============================第二个路由切换页面.vue=================================
<template>
<div class="package">

<v_header></v_header>
<v_subjectTop :text='"问政热点"' :left_show="true" :right_show="true" :pos_right="true"></v_subjectTop>
<div id="wrapper">
  <div id='scroller'>
    <v_list :prop_type="'1'"></v_list>
  </div>
</div>
<v_footer></v_footer>

</div>
</template>
<script>
import v_header from '../components/header.vue'
import v_subjectTop from '../components/subjectTop.vue'
import v_list from '../components/list.vue'
import v_footer from '../components/footer.vue'
export default {

data () {
  return {
    alloyTouch:{},
  }
},
mounted() {
  var self=this;
  var alloy = {};
  alloy.scroller = document.getElementById("scroller");
  alloy.loading = false;
  Transform(alloy.scroller, true);
  self.alloyTouch = new AlloyTouch({
    touch: "#wrapper",
    vertical: true,
    target: alloy.scroller,
    property: "translateY",
    maxSpeed: 2,
    outFactor: 0.2,
    min: 160 * -20 + window.innerHeight - 202 - 50,
    max: 0,
    touchStart: function () {
      self.reastMin(alloy,self.alloyTouch);
    },
    lockDirection: false,
    change: function (v) {
      self.alloyTouchChange(v,alloy,self.alloyTouch);
    }
  });
  document.addEventListener("touchmove", function (evt) {
    evt.preventDefault();
  }, false);
},
methods: {
  alloyTouchChange(v,alloy,alloyTouch){
    var self = this;
    if (v <= alloyTouch.min + 5 && !alloy.loading) {
      alloy.loading = true;
      self.loadMore(alloy,alloyTouch);
    }
    if (v < 0) {
      if (v < -140) v = -140;
      var scale = (240 + v) / 240;
    } else {
      var scale = 1 + v / 240;
    }
  },
  loadMore(alloy,alloyTouch) {
    var self = this;
    setTimeout(function () {
      //self.$store.dispatch('actDefaultNewsList');
      alloy.loading = false;
      self.reastMin(alloy,alloyTouch);
    }, 500)
  },
  reastMin(alloy,alloyTouch) {
   // let loadHeight = parseInt(getComputedStyle(alloy.load).height);
    let scrollHeight = parseInt(getComputedStyle(alloy.scroller).height);
    alloyTouch.min = -1 * scrollHeight + window.innerHeight ;
  }
},
computed: {
},
components: {
  v_header,v_subjectTop,v_list,v_footer
}

}
</script>
<style lang="scss" scoped>
#scroller, #wrapper {

position: absolute;
width: 100%;

}

#wrapper, body {

overflow: hidden;

}

#wrapper {

z-index: 1;
top: 0;
bottom: 0;
left: 0;

}

#scroller {

padding-top: 2.55rem;
z-index: 1;
-webkit-tap-highlight-color: rgba(0,0,0,0);
will-change: transform;
-webkit-transform: translateZ(0);
transform: translateZ(0);
-webkit-touch-callout: none;
-webkit-user-select: none;
user-select: none;
-webkit-text-size-adjust: none;
text-size-adjust: none;
-webkit-perspective: 1000;
-webkit-backface-visibility: hidden;
backface-visibility: hidden;

}
</style>

//==============================第3个路由切换页面.vue=================================

<template>
<div class="consult">

  <v_header></v_header>
  <subjectTop :text='"咨询帮助"' :left_show="true" :right_show="true" :pos_right="true"></subjectTop>
  <h1>{{title}}</h1>
  <div class="form">
      <div class="form-group xh-marginBottom-20">
        <input class="input" type="text"  placeholder="请输入姓名"/>
        <span class="error-text none">错误</span>
      </div>
      <div class="form-group xh-marginBottom-20 input sex clear">
          <span class="radio-group border-right pull-left">
            <span>男</span>
            <span class="icon">
              <span class="" data-sex="男">
                  <i></i>
                </span>
            </span>
          </span>
          <span class="radio-group pull-left">
              <span>女</span>
              <span class="icon">
                <span class="none" data-sex="女">
                  <i></i>
                </span>
              </span>
            </span>
      </div>
      <div class="form-group xh-marginBottom-20">
        <input class="input-year input" type="number"  placeholder="请输入年龄"/>
        <span class="error-text none">错误</span>
      </div>
      <div class="form-group xh-marginBottom-20">
        <input class="input" type="text"  placeholder="请输入联系电话"/>
        <span class="error-text none">错误</span>
      </div>
      <div class="form-group xh-marginBottom-20">
        <input class="input" type="text"  placeholder="请输入地址"/>
        <span class="error-text none">错误</span>
      </div>
      <div class="form-group xh-marginBottom-20">
        <input class="input" type="text"  placeholder="请输入诉求标题"/>
        <span class="error-text none">错误</span>
      </div>
      <div class="form-group xh-marginBottom-20 xh-relative">
        <textarea class="sq input"  cols="30" rows="6"></textarea>
        <span class="tip-text">请输入您的诉求</span>
      </div>
      <div class="form-group">
        <button class="btn blue sure" type="button">确定</button>
      </div>
  </div>
  <div class="xh-marginBottom-20">
    <p class="wxts">
      ◆温馨提示<br/>
      1、请如实填写信息,文字简练、表达清楚;<br/>
      2、收到诉求后我们将尽快与您取得联系,请保持电话畅通;<br/>
      3、您还可以拨打“幺婶热线”023-65831380与我们联系;<br/>
      4、商业广告和垃圾信息谢绝提交。<br/>
    </p>
  </div>
  <v_footer class="footer"></v_footer>

</div>
</template>

<script>
import Vue from 'vue'
import v_header from '../components/header.vue'
import subjectTop from '../components/subjectTop.vue'
import v_footer from '../components/footer.vue'
export default {

data () {
  return {
    form:{
      sex : '男',
      year : 80,
    },
    title :'种植养殖有难题?家长里短说不清?政策法规需解答?环境脏乱要投诉?……无论您遇到什么大事小事,欢迎告诉我们您的诉求,热心肠的“幺婶”来帮您!',
  }
},
mounted (){
  var vm = this;
  const form =$('.form');
  document.addEventListener('touchmove', function (e) {  //取消阻止默认行为
    e.returnValue = true;
  }, false);
  form.find('*').each(function(){
    let self = $(this);
    if(self.hasClass('sq')){
      let tip = self.next();
      self.off('focus').on('focus',function () {
        tip.addClass('none');
      }).off('blur').on('blur',function () {
        if(self.val() == null){
          tip.removeClass('none');
        }
      });
    }else if(self.hasClass('sex')){
      const radioGroup = self.children();
      radioGroup.each(function () {
        let _self = $(this);
        let span = _self.find('.icon > span');
        let val = '';
        _self.off('touchstart').on('touchstart',function () {
          _self.parent().find('.icon > span').addClass('none');
          span.removeClass('none');
        });
      });
    }else if(self.hasClass('input-year')){
    }
  });
},
methods: {

},
computed: {

},
watch:{

},
components: {
  v_header,subjectTop,v_footer
}

}
</script>
<style lang="scss" scoped>
.consult{

h1{
  font-size: .3rem;
  text-align: left;
  line-height: 150%;
  padding: .2rem .15rem;
  border-bottom: 1px solid #ddd;
}
.form{
  padding: .2rem .15rem;
  input{
    display: block;
    height: .6rem;
    line-height: .6rem;
    padding: 0 .15rem;
    color: #333;
  }
  .input.border-bottom{
    border: none;
    border-bottom: 1px solid #CECECE;
  }
  .sex{
    height: .6rem;
    line-height: .6rem;
  }
  .radio-group{
    color: #333;
    display:block;
    width:50%;
    text-align:center;
    text-indent: 0;
    .icon{
      width: .36rem;
      height: .36rem;
      vertical-align: middle;
      display: inline-block;
      border-radius: 50%;
      -ms-border-radius: 50%;
      -moz-border-radius: 50%;
      -webkit-border-radius: 50%;
      -o-border-radius: 50%;
      background-color: #e5e5e5;
      position: relative;
      i{
        display: block;
        position: absolute;
        left: 50%;
        top:50%;
        background-color: #777;
        transform: translate(-50%,-50%);
        width: .2rem;
        height: .2rem;
        border-radius: 50%;
        -ms-border-radius: 50%;
        -moz-border-radius: 50%;
        -webkit-border-radius: 50%;
        -o-border-radius: 50%;
      }
    }
  }
  .border-right{
    border-right: 1px solid #ddd;
  }
}
.sure{
}
.wxts{
  font-size: .3rem;
  line-height: 150%;
  border-top:1px solid #ddd;
  padding: .2rem .15rem .8rem;
}
.sq{
  color: #333;
  line-height: 150%;
}
.tip-text{
  position: absolute;
  left: .15rem;
  top:.15rem;
  font-size: .3rem;
  color: #666;
}
.blue{
  background: #6292cc!important;
  font-size: .32rem;
}

}
</style>
<style scoped>
.btn{ overflow:hidden; border:none; text-align:center; font-size:14px; border-radius:3px; color:#fff; background:#7296cc;}

.swiper-container {

margin:0 auto;
position:relative;
overflow:hidden;
-webkit-backface-visibility:hidden;  /*隐藏被旋转的 div 元素的背面:*/
/* Fix of Webkit flickering */
z-index:4;

}
.swiper-wrapper {

position:relative;
width:100%;
-webkit-transition-property:-webkit-transform, left, top;
-webkit-transition-duration:0s;
-webkit-transform:translate3d(0px,0,0);
-webkit-transition-timing-function:ease;

}
.swiper-free-mode > .swiper-wrapper {

-webkit-transition-timing-function: ease-out;
margin: 0 auto;

}

.addressSelection-box{ opacity:0; position:fixed; bottom:-160px; left:0; z-index:88; width:100%; background:rgba(255,255,255,0.8); transition:all ease-out 0.3s;-webkit-transition:all ease-out 0.3s;}
.addressSelection-box.active{ opacity:1; bottom:0;}
.addressSelection-box .option{ position:relative; float:left; width:100%;}
.addressSelection-box .swiper-container{ width:100%; height:120px;-webkit-transform-style: preserve-3d;}
.addressSelection-box .swiper-slide { width:100%; line-height:30px; text-align:center; font-size:.3rem; color:#999;}
.addressSelection-box .swiper-slide-active{ color:#000;}
.addressSelection-box .checked{ position:absolute; left:0%; top:30%; z-index:1; width:100%; height:18px; margin-top:-7px; border-bottom:1px solid #999; border-top:1px solid #999;}
.addressSelection-box .swiper-slide-prev,.addressSelection-box .swiper-slide-next{color: #646464;}

.addressSelection-box .operation{ position:absolute; top:-30px; left:0; width:100%; padding:3px 0;background:#ddd;}
.addressSelection-box .operation .btn{ display:inline-block; width:20%; height:26px;margin:0 3%; line-height:26px; }
.addressSelection-box .operation .cancel-btn{ float:left;}
.addressSelection-box .operation .confirm-btn{ float:right;}
.address{ width:80%; margin:20px;}
</style>


  1. ;
阅读 10.5k
2 个回答

因为vue-router 第一次加载页面时需要加载全部的js,如果你的设置的router比较多,打包的js比较大,可以试试用vue-router的异步加载js的方法

路由懒加载

以为你使用了组件的懒加载,所以每次第一次切换路由的时候,都要去加载相应的组件的js文件,需要等文件加载完之后,路由才能切换过去;后面切换的话js都下载过了,所以切换就不卡了

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏