墨瞳漫画h5一期 vuejs总结

媒介

博主也是vuejs萌新,公司仅我一个前端,收到做h5的需求后,立时想到要用下vuejs,因而压服指导,最先逐步研讨,如今记载一下踩到的坑。这些坑主假如在一些组件的运用上,别的的只需好好看官方文档就好了,vue,vue-router, vuex的文档相称重要。

迎接体验提bug 墨瞳漫画 m.cm233.com

vue-router

router这里踩的坑主假如组件的重用。构建单页面大型运用的话,肯定要开启组件的缓存的,由于平常会要求退却的时刻不要从新加载页面,而且要记着原始的转动位置。
起首,引入router-view的处所要加上keep-alive

<router-view keep-alive></router-view>

然后开启html5 history形式,并开启位置记载

const router = new Router({
  history: true, // use history=false when testing
  saveScrollPosition: true
})

开启keep-alive今后,当要求一个组件的内容发生变化时,比方 漫画概况页面是一个路由带参数的组件,当参数变化时,router会重用这个组件,而不是从新要求数据,这显然是不符合要求的,所以准确的姿态是:
起首,用一个字段保留这个路由参数,
用router的钩子函数data猎取路由变化参数,保留到字段里


route:{
  data: function(transition){
      this.bookId = transition.to.params.id;
  }
}

写一个watcher来拉取数据并添补模版,由于在data钩子函数中,我们已修正了相应字段,所以当路由参数变动时会直接触发这个watcher

watch: {
  'bookId' : function(val){
    //do something
  }
}

假如是多个参数的,能够把这些参数放到一个对象里,watcher采纳深监测

route:{
  data: function(transition){
      this.watcher.type = transition.to.params.type;
      this.watcher.id = transition.to.query.id;
  }
},
watch : {
  'watcher' : {
    handler: function(val){
    //do something
    window.scrollTo(0,0);// 不运用缓存时,不运用记载好的用户位置,滑倒顶部
    },
    deep: true
  }
}

一最先没有用这类要领出了许多的bug,改了今后,路由和缓存方面的逻辑霎时就变得清楚了,组件的切换也越发流通了。
第二个坑就是关于缓存页面阅读位置的记载,router是经由过程html5 history的pushState来记载当前转动位置的,切换路由的时刻,把当前位置push进去,用户退却时,会触发onpopstate事宜,这个时刻再把位置取出来并转动到指定位置,然则!某些阅读器自身也设置了一些新鲜的位置转动,vue-router的转动就失效了,所以须要耽误实行一下

   window.addEventListener("popstate",function(e){
     setTimeout(()=>{
       window.scrollTo(0,e.state.pos.y);//经由过程打log,发现了位置记载在这个变量里了
     },300)
    },false);

但是,阅读器只能记载一个位置,所以会有如许的状况: 从m.cm233.com 到 m.cm233.com/book,再返回到m.cm233.com,这时候阅读器跳到了当时记载的位置,然则再前进到/book时,阅读器照样会停在首页的谁人位置上,这个bug临时还没有处理,幸亏用户场景不是许多。所以通知我们,子页面路由参数变化的时刻,要把转动条人工弄到最上面,要不然就会转动到进口页面的阅读位置。也就是watcher里还要加一句如上的转动。

页面题目也是要手动变动的,所以每一个页面要放一个特地的title变量存一下,然后在data钩子函数(用于组件缓存时) 和 路由参数的watcher(用于组件更新时) 里 都转变title

route:{
  data: function(transition){
    this.title = 'hiahia';
    document.title = this.title;
  }
},
watch : {
  'id' : function(val){
    this.title = 'hiahia';
    document.title = this.title;
  }
}

一般页面的题目不是牢固的,用变量存储title,主假如为了记着上一次组件被用的时刻的title,以便于重用的时刻替换。

但是,ios微信不会监测document.title的变化,所以要写一个特地针对它的hack,经由过程建立iframe

//全局函数
window.isWeiXin = function(){
    var ua = window.navigator.userAgent.toLowerCase();
    if(ua.match(/MicroMessenger/i) == 'micromessenger'){
        return true;
    }else{
        return false;
    }
}

window.weiXinChange = function(title){
  if(window.isWeiXin()){
    document.title = title;
    var iframe = document.createElement('iframe');
    iframe.src = './favicon.ico';
    iframe.style.display = 'none';
    iframe.onload = function(){
      setTimeout(function() {
        document.body.removeChild(iframe);
      }, 0);
    }
    document.body.appendChild(iframe);
  }
}

//组件中

route:{
  data: function(transition){
    this.title = '墨瞳漫画';
    document.title = this.title;
    window.weiXinChange(this.title);
  }
},
watch : {
  'id' : function(val){
    this.title = '墨瞳漫画';
    document.title = this.title;
    window.weiXinChange(this.title);
  }
}

vue-infinite-scroll (directive)

(为何不本身写!)

组件地点 https://github.com/ElemeFE/vue-infinite-scroll 饿了么出品

运用要领
main.js

import Scroll from 'vue-infinite-scroll'
Vue.use(Scroll)

组件中

  <dl v-infinite-scroll="loadMore()" infinite-scroll-disabled="busy" infinite-scroll-distance="7">
    <template v-for="item in list">
      <dd class="page-item">
      </dd>
    </template>
  </dl>

个中busy这个变量比较重要,他掌握着这个指令是不是继承实行,当没有下一页数据的时刻,应当把busy置为true来封闭转动加载。正在读取下一页数据时,要先把busy置为true,数据返回时在置为false

loadmore(){
  this.busy = true;
  someApi.someFunction().then((data) => {this.busy = false;})
}

然则这个组件在路由切换的时刻会出题目,routerView被移除时,组件会触发加载(也许是由于页面高度倏忽陷落),而且会一向加载到我们本身设置的住手前提(busy=true)。所以脱离页面的时刻,须要在路由的deactivate钩子函数里把转动关掉,再次进入页面的时刻再开启(路由无变化在data钩子函数里开启,有变化的话在watcher里开启,假如不须要在路由转变时向子组件延时通报参数也能够都在data钩子函数里开启)

route:{
    deactivate: function(transition){
      this.busy = true;
      transition.next();
    },
  data: function(transition){
    if(){
      this.busy = false;
    }//这里输入组件路由参数没有变化的前提
  }
}

lazyload

(为何不本身写!)
网上找了几个lazyload的组件,都不太好使,就本身改了一个,是改了一个,原组件叫vue-lazyload, 缺点还挺多的,写这个组件的人预计没有真正在大项目中用过就渐渐宣布在npm了,es6版本也写的不三不四的 - -,不过照样很厉害,本身写的话缺点肯定会更多。我改后的放在https://github.com/Ganother/blog/blob/master/lazyload.js了,是个较为稳固的版本。个中过渡动画写在img-loaded这个class里

/*简朴的透明度渐入,图片加载完成后会删掉这个class,以防router切换缓存页面时再次引发动画*/
.img-loaded {
  animation: loaded .2s ease-in-out;
 }
 @keyframes loaded {
   0%{
     opacity: 0;
   }
   100%{
     opacity: 1;
   }
 }
let loadingJpg = require('assets/loading.jpg');//这里引入一张loading图,会被转成base64
Vue.use(VueLazyload, {
 preLoad: 1.3, //图片顶端距窗口顶端1.3个屏幕高度时最先加载
 loading: loadingJpg,
 error: loadingJpg
})

自适应的图片:假如服务端传过来的图片带了宽高信息,能够在img外层包一个class为img-bar的元素,图片过来的时刻先设置一个min-height为相应高,组件在图片加载后会自动取掉这个min-height。如许能够防备loading图和图片大小不一样引发的页面跳动继而致使的加载图片机遇毛病。

vue-resource

跨域时,会先发送一个空的options要求来检察接口是不是是支撑跨域,再发送一次实在要求。还不是很相识这类体式格局的优点,当接口较多时,要求数目多了一倍也是有点为难的,所以要设置一下。而且假如接口每次都打印空参数的log的话。。。嗯。

Vue.http.options.emulateJSON = true;
Vue.http.options.headers={
    'Content-Type':'application/x-www-form-urlencoded; charset=UTF-8'
};

构造目次

vue-cli直接构建的,src里的目次以下

api 放一些ajax要求接口的函数
assets 放一些静态资本,图片,大众sass
directives 放一些指令js,比方修正后的lazyload
pages 页面进口组件,用在router中
components 小组件们
vuex vuex
app.vue
main.js

别的,能够修正下天生的静态文件,vue-cli默许宣称的静态文件时候戳是加在文件名上的,如app.fefdfd7s8f78sd7.js,如许版本迭代很快后会使服务器上积存过量无用文件,我们愿望如许加时候戳 app.js?t=32j32ih4u32h 所以改一下webpack.prod.conf.js就好了,以下

  output: {
    path: config.build.assetsRoot,
    filename: utils.assetsPath('js/[name].js?t=[chunkhash]'),
    chunkFilename: utils.assetsPath('js/[id].js')
  }


    new ExtractTextPlugin(utils.assetsPath('css/[name].css?t=[contenthash]')),
    原文作者:Ganother
    原文地址: https://segmentfault.com/a/1190000006964089
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞