干货分享:vue2.0做移动端开发用到的相关插件和经验总结(更新)

16,940 阅读9分钟

最近在用vue2.0做微信公众号相关的前端开发,经过这次开发实践,现将项目中用到的相关比较实用的插件及遇到的相关问题进行整理,希望和大家共同交流......

  • cssrem:一个CSS值转REM的VSCode插件;
  • lib-flexible:移动端弹性布局适配解决方案;
  • vue-touch:移动端相关点击,滑动,拖动,多点触控等事件封装;
  • vee-validate:适用于vue项目中表单验证插件;
  • better-scroll :可能是目前最好用的移动端滚动插件;
  • fastclick:解决移动端click 300ms延迟
  • vConsole:手机前端开发调试利器 
  • webpack之proxyTable设置跨域
  • vue组件之间通信(父向子通信,子向父通信,非父子通信)方法示例;
  • ref特性的使用;
  • vue中setTimeout,setInterval的使用;
  • 监听鼠标滚动事件,实现头部悬浮效果(this.$nextTick);
  • new FormData()上传图像;
  • vue,@click="event()",添加()与不添加()的区别;
  • H5,设置textarea高度随文字输入增高;
  • vue,监听滚动条滚动到最底部,加载下一页数据;

cssrem

介绍:一个CSS值转REM的VSCode插件。我们在做移动端开发时,为了网页适配,一般会将像素单位px转换为rem.在用vscode开发时,我们可以安装cssrem这个插件。
插件效果如下:
默认配置:

“cssrem.rootFontSize”: root font-size (unit: px), 默认为: 16;
“cssrem.fixedDigits”: px转rem小数点最大长度,默认:6;
“cssrem.autoRemovePrefixZero”:自动移除0开头的前缀,默认:true

项目中配置:

 "cssrem.fixedDigits": 2,//px转化为rem保留2位小数
 "cssrem.rootFontSize":75//px转化为rem基准

"cssrem.rootFontSize":75, //px转化为rem基准75px
由于我在项目中使用了淘宝弹性布局方案lib-flexible,UI同事是按照iphone6尺寸(750px)进行设计的。项目在iphone6屏幕时,root,html的font-size:75px,所以项目中配置rem基准为75px;
"cssrem.fixedDigits:2", //  即设置px转rem最大小数点为2位数;
使用方法:
这里是vsCode的配置方法:
文件-->首选项--设置-->“搜索cssrem”,将自己的设置放入右边覆盖“默认设置”,重启编辑器即可;如图:


lib-flexible

  • lib-flexible介绍:

lib-flexible为移动端弹性布局适配解决方案。很多的大公司,如网易,淘宝等,都在用它作为移动端布局。

  • 使用方法:
安装lib-flexible:

npm install lib-flexible --save

在项目入口文件main.js 中引入lib-flexible

import 'lib-flexible'

去掉目标文件的index.html头里的meta标签。
<meta name="viewport" content="width=device-width, initial-scale=1.0"> //不要写上边这行meta,flexible会为根据屏幕自动给我加上,如果你自己加了, 那么flexible会根据你加的值来计算,也就会出现固定的值,安卓和苹果都会一样了。data-dpr有可能是固定的了
知识延伸:
在做像素单位适配的时,你也可以不用安装cssrem,直接用px,我们可以通过安装插件:px2rem-loader并进行相应的配置,通过编译之后,自动将px转换为rem;
使用方法,可参考官网;但是其有一定的局限性,即只能将.vue文件style标签中的px转成rem,对外部引入css,px2rem能不能转换rem问题;
对于引入了第三方框架,他们的样式是另一套写法,样式会被flexible转换,就会破坏框架的样式。
如果在.vue文件style中的某一行代码不希望被转成rem,只要在后面写上注释 /* no*/就可以了。

vue-touch

  • vue-touch介绍:

vue-touch其实封装了 hammer.js的方法,针对触屏的6大事件进行监听。官网

  • 使用方法:
安装vue-touch:

npm install vue-touch@next

嵌入vue-touch:
在vue入口文件main.js中将其注册为全局组件:

var VueTouch = require('vue-touch')
Vue.use(VueTouch, {name: 'v-touch'})

使用实例:

//左划 默认渲染为div   data为参数
<v-touch v-on:swipeleft="onSwipeLeft(data)">Swipe me!</v-touch>
//点击   渲染为一个a标签
<v-touch tag="a"  v-on:tap="onTap">Tap me!</v-touch>
//点击   渲染为p标签 
<v-touch tag="p" v-on:tap="onTap">Tap me!</v-touch>常用的事件有:swiper(滑动事件)、tap(短时间内的点击事件)、press(事件大于tap的按压事件)

  • api及相关的事件:
1、pan,触屏中的拖动事件,在指定的dom区域内,一个手指放下并移动事件
事件类型有:pan, panstart, panmove, panend, pancancel,
panleft, panright, panup, pandown;
使用方法为:v-on:panstart="callback";
2、Swipe:滑动事件,在指定的dom区域内,一个手指快速的在触屏上滑动。
事件类型有:swipe, swipeleft, swiperight,
swipeup, swipedown
使用方法为:v-on:swipeleft="callback";
3、Tap:在指定的dom区域内,一个手指轻拍或点击时触发该事件(类似PC端的click)。该事件最大点击时间为250毫秒,如果超过250毫秒则按Press事件进行处理。
事件类型:tap
使用方法:v-on:tap="callback"
4、Press:在指定的dom区域内触屏版本的点击事件,这个事件相当于PC端的Click事件,该不能包含任何的移动,最小按压时间为500毫秒,常用于我们在手机上用的“复制、粘贴”等功能。该事件分别对以下事件进行监听并处理:
事件类型:press, pressup
使用方法:v-on:press = "callback"
5、Rotate事件:在指定的dom区域内,当两个手指或更多手指成圆型旋转时触发(就像两个手指拧螺丝一样)。该事件分别对以下事件进行监听并处理
事件类型:rotate, rotatestart, rotatemove,
rotateend, rotatecancel,
使用方法:v-on:rotate = "callback"
6、Pinch:在指定的dom区域内,两个手指(默认为两个手指,多指触控需要单独设置)或多个手指相对(越来越近)移动或相向(越来越远)移动时事件。该事件事以分别对以下事件进行监听并处理:
Pinchstart:多点触控开始、Pinchmove:多点触控过程、Pinchend:多点触控结束、Pinchcancel:多点触控取消、Pinchin:多点触控时两手指距离越来越近、Pinchout:多点触控时两手指距离越来越远
注意事项:
1、注意:vue-touch 使用的是2.0.0版本 需要与vue2.0.0兼容;
应用实例:
通过手势滑动,进行页面的切换,如:

 swiperleft: function () {
    this.$router.push({'path':'/queuehistory'});
 }

vee-validate

  • vee-validate介绍:

vee-validate为适用于vue项目中表单验证插件.引入vee-validate,会更加方便我们进行表单验证。 官方网址.

  • 安装vee-validate

npm install vee-validate@next --save

注意:@next,不然是Vue1.0版本
安装时要注意安装的版本,不同的版本使用的方式不一样。
如果在安装完成后,且在mian.js中进行了正确的引用,如果在控制台,出现如下报错信息:
IMPORTED_MODULE_5_vee_validate__.a.addLocale is not a func
则说明,你安装的版本过高,请重新卸载,安装较低版本即可;我的项目中安装的版本为:2.0.0-rc.25。
  • main.js里引用vee-validate插件

import Vue from 'vue' 
import VeeValidate,{ Validator } from 'vee-validate' 
import zh_CN from 'vee-validate/dist/locale/zh_CN' //引入中文包,提示信息可以以中文形式显示

Validator.addLocale(CN) // 设置提示信息中文方式显示
Vue.use(VeeValidate, {  locale: 'zh_CN'})

  • 扩展自定义验证规则

Validator.extend('phone', 
{ messages:{
  zh_CN: field => '请输入正确手机号'
},
validate: value => {
    return /^(13[0-9]|14[579]|15[0-3,5-9]|16[6]|17[0135678]|18[0-9]|19[89])\d{8}$/.test(value)
}
});
Validator.extend('isCard', {
  messages: {   
   zh_CN: field => '请输入正确身份证号'
  },
  validate: value => {   
   return /(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)/.test(value)
  }
})

  • 自带规则的中文设置

const dictionary = {  
   zh_CN: {  
     messages: { 
      required: (val) => {        
          let msg = ''        
            switch (val) {         
             case 'ownerPhone':          
                  msg = '手机号'           
                  break        
            }        
            msg = msg + '不能为空哦'       
             return msg     
             },      
       numeric: (val) => {      
          let msg = ''     
           switch (val) {            
              case 'houseShi':     
                   msg = '居室'      
                   break          
           }      
          msg = msg + '只能为数字'       
          return msg      
      } 
    }  
}}
Validator.updateDictionary(dictionary)

  • 组件中使用
插件自带规则和自定义规则,写法:v-validate="'required|ownerPhone'",设置name属性,通过v-show="errors.has()"来进行name属性的监听,显示和隐藏相关的提示信息;

<form class="form" autocomplete="off" @submit.prevent="validateBeforeSubmit">
   <div class="form-item">
     <input type="number"  placeholder="请输入你的手机号"  v-model="params.ownerPhone"  v-validate="'required|ownerPhone'" name="ownerPhone">  
     <span v-show="errors.has('ownerPhone')" class="help is-danger">
          {{ errors.first('ownerPhone') }}
     </span>  
   </div>
   <button class="form-btn bg-blue" type="submit">登录</button>
</form>

更详细的语法学习,请参见vee-validate官网

better-scroll

  • better-scroll介绍:
better-scroll,官方网址,better-scroll 是一款重点解决移动端(现已支持 PC 端)各种滚动场景需求的插件。它的核心是借鉴的 iscroll 的实现,它的 API 设计基本兼容 iscroll,在 iscroll 的基础上又扩展了一些 feature 以及做了一些性能优化。
better-scroll 是基于原生 JS 实现的,不依赖任何框架。它编译后的代码大小是 63kb,压缩后是 35kb,gzip 后仅有 9kb,是一款非常轻量的 JS lib。

  • 使用方法

安装方法

npm install --save better-scroll;

起步
better-scroll 最常见的应用场景是列表滚动,我们来看一下它的 html 结构:

<div class="wrapper">
  <ul class="content">
    <li>...</li>
    <li>...</li>
    ...
  </ul>
  <!-- 这里可以放一些其它的 DOM,但不会影响滚动 -->
</div>

上面的代码中 better-scroll 是作用在外层 wrapper 容器上的,滚动的部分是 content 元素。这里要注意的是,better-scroll 只处理容器(wrapper)的第一个子元素(content)的滚动,其它的元素都会被忽略。
最简单的初始化代码如下:

import BScroll from 'better-scroll'
let wrapper = document.querySelector('.wrapper')
let scroll = new BScroll(wrapper)

结合接口下拉刷新加载更多数据

export default  {  
   methods:{	
    async getMyBillList() {
        const res = await getMyBillList(reqData);
        if (res.status.code == "200") {		
 	  this._houseScroll();  // 结合接口初始化scroll数据		
        }else{		 
          console.log("接口调用失败~");	
	}	
    },	
   _houseScroll(){   
         this.$nextTick(() => {
                if (!this.houseScroll) {
                    let wrapper = document.querySelector('.wrapper'); // scroll容器
		                      // new Bscroll(),初始化容器;
                    this.houseScroll = new Bscroll(wrapper,{
                            scrollY: true,
                            probeType: 3,
                            click: true,
                            pullUpLoad: {
                              threshold: -100 // 在上拉到超过底部 20px 时,触发 pullingUp 事件
                            }
                        }
                    );
		                  // 初始化上拉刷新加载更多方法
                    this.houseScroll.on("pullingUp", () => {
                        this.pageNo++;
                        if (this.totalPage >= this.pageNo) {
                             this.pageNo++; // 通过pageNo增加,加载第二页的数据
                             this.getMyBillList();
                             this.loading = true;
                        } else {
                            this.loading = false;
                            this.loadingOver = true;
                        }
                    });
                } else {
                    this.houseScroll.finishPullUp();
                    this.houseScroll.refresh();
                }
            });
    }
   }
}
     				

fastclick插件:解决移动端click 300ms延迟

移动端项目中,在某些机型某些浏览器下,存在click事件300ms延迟的问题,影响用户满意度。原因是:从点击屏幕上的元素到触发元素的 click 事件,移动浏览器会有大约 300 毫秒的等待时间,因为它想看看你是不是要进行双击(double tap)操作。

vue项目中,可以通过引入fastclick第三方依赖包来解决。

安装方法:

npm  install --save fastclick

使用方法:

在main.js中

import fastclick from 'fastclick'
fastclick.attach(document.body)

也可以直接下载fastclick.js,在相应页面直接引用。

手机前端开发调试利器 – vConsole

vConsole介绍:一个轻量、可拓展、针对手机网页的前端开发者调试面板。

移动端项目,由于在移动端无法打开控制台,所以无法像pc端chrome控制台那样直观查看console信息;不过我们可以使用vConsole插件进行调试。

使用方法如下:

安装vConsole:

npm install vconsole --save-dev

在main.js中引用并实例化:

import VConsole from 'vconsole';const vConsole = new VConsole(); // 不使用的时候,可以将这句屏蔽掉;

此时可以使用console.log
原理:改写了console.log,重写了实现,用vConsole代理

结果就会出现如图 浮动的按钮,点开之后,就可以看到里面的console信息了;


webpack之proxyTable设置跨域

在平时项目的开发环境中,经常会遇到跨域的问题,尤其是使用vue-cli这种脚手架工具开发时,由于项目本身启动本地服务是需要占用一个端口的,所以必然会产生跨域的问题。在使用webpack做构建工具的项目中,使用proxyTable代理实现跨域是一种比较方便的选择。

proxyTable相关配置及使用说明:

当我们用vue-cli构建项目时,需要在config/index.js文件中,找到dev对象下proxyTable对象进行跨域设置,配置如下:

dev: {
  env: require('./dev.env'),
  port: 8080,
  autoOpenBrowser: true,
  assetsSubDirectory: 'static',
  assetsPublicPath: '/',
  cssSourceMap: false,
  proxyTable: {
    '/api': {
      target: 'http://www.abc.com',  //目标接口域名
      changeOrigin: true,  //是否跨域
      secure: false, // 允许https请求      pathRewrite: {
        '^/api': '/api'   //重写接口
      }
    }
}

proxyTable配置的意思为:使用字符串"/api"来代替目标接口域名;如果接口地址为"user/getUserInfo",我们可以在所有的接口地址前面加上"/api/"用于设置代理;如:

'http://localhost:8080/api/user/getUserInfo' ===> 'http://www.abc.com/api/user/getUserInfo'

如果你不想每次请求地址中都带有"/api/",则可以设置

 pathRewrite: {
    '^/api': ''   // 后面可以使重写的新路径,一般不做更改
 }

表现结果为:

'http://localhost:8080/api/user/getUserInfo' ===> 'http://www.abc.com/user/getUserInfo'

另外一种情况是,我们不需要在每个接口地址前添加"/api/",只需要用接口本身的地址,不需要重新路径即可。如果接口为:"/v2/cotton/get_app_list",使用"/v2"做代理;如下:

dev: {
  proxyTable: {
    '/v2': {
      target: 'http://www.abc.com',  //目标接口域名
      changeOrigin: true,  //是否跨域
      secure: false,  // 允许https请求      
      // 这里去掉了重新设置新路径,因为接口地址本身就是以"/v2/"开头的;
    }
}

'http://localhost:8080/v2/cotton/get_app_list' ===> 'http://www.abc.com/v2/cotton/get_app_list'
// http://localhost:8080/v2表示http://www.abc.com

默认情况下,不接受运行在 HTTPS 上,且使用了无效证书的后端服务器。如果你想要接受,修改配置如下:

proxy: {
  "/api": {
    target: "https://www.abc.com",
    secure: false
  }
}


vue组件之间通信

  • 父向子传递数据通过props

/**父组件代码:**/
<template>
    <header-box :title="text"></header-box>
</template>
<script>
    import HeaderBox from './header'
    export default {
        name: 'index',
        components: {
            HeaderBox 
        },
        data () {
            return {
                text: '首页'
            }
        }
    }
</script>

/**子组件代码**/
<template>
    <header>
        {{thisTitleTxt}}
    </header>
</template>
<script>
    export default {
        name: 'headerbox',
        props: {
            text: String
        },
        data () {
            return {
                thisTitleTxt: this.text
            }
        }
    }
</script>

  • 子向父传递数据

子组件向父组件传递分为两种类型。
1、子组件改变父组件传递的props(你会发现通过props中的Object类型参数传输数据,可以通过子组件改变数据内容。这种方式是可行的,但是不推荐使用,因为官方定义prop是单向绑定);
2、通过$on和$emit;即子组件中通过$emit()来触发事件;父组件中通过依附在组价元素上的:on方法来响应事件。

*通过$on,$emit*
**父组件代码**
<template>
    <div id="counter-event-example">
      <p>{{ total }}</p>
      <!--父组件中通过v-on:key="function"来触发方法的执行-->
      <button-counter v-on:increment="incrementTotal"></button-counter>
    </div>
</template>
<script>
    import ButtonCounter from './buttonCounter'
    export default {
        name: 'index',
        components: {
            'button-conuter': ButtonCounter
        },
        data () {
            return {
                total: 0
            }
        },
        methods: {
            incrementTotal () {
                this.total++
            }
        }
    }
</script>

**子组件代码**
<template>
    <button @click="incrementCounter">{{counter}}</button>
</template>
<script>
    export default {
        name: 'button-counter',
        data () {
            return {
                counter: 0
            }
        },
        metheds: {
            incrementCounter () {
                this.$emit('increment');// 子组件中通过this.$emit('key',value)触发事件信号
                this.counter++
            }
        }
    }
</script>
  • 非父子组件传递数据;

通过使用一个空的Vue实例作为中央事件总线。

**main.js**
let bus = new Vue()
Vue.prototype.bus = bus;

相邻组件1,通过$emit()传递数据
this.bus.$emit("toChangeTitle","首页");

相邻组件2,通过$on()接收数据
mounted(){   
   this.bus.$on('toChangeTitle', function (title) {
       console.log(title)
  })
}

ref特性的使用

ref 被用来给元素或子组件注册引用信息。引用信息将会注册在父组件的 $refs 对象上。

如果在普通的 DOM 元素上使用,引用指向的就是 DOM 元素;如果用在子组件上,引用就指向组件实例:

<div id="app"> 
    <input type="text" ref="input1" v-model="name"/>  
    <button @click="add">添加</button>
    <!-- `vm.$refs.child` will be the child component instance -->
    <child-component ref="child"></child-component>
</div>
<script>
export default{
  data(){
    return {
       name:"xiaoming"
    }
   },
  created(){
    this.$nextTick(()=>{
        console.log(this.$refs.input1.value);
    });
  },   
  methods:{
     add(){
         this.$refs.input1.value = "22"; //this.$refs.input1 减少获取dom节点的消耗
     }
   }
}
</script>

v-for 用于元素或组件的时候,引用信息将是包含 DOM 节点或组件实例的数组。

关于 ref 注册时间的重要说明:因为 ref 本身是作为渲染结果被创建的,在初始渲染的时候你不能访问它们 - 它们还不存在!$refs 也不是响应式的,因此你不应该试图用它在模板中做数据绑定。

通过在引用的子组件上使用ref属性实现父组件调用子组件的方法及属性

在父组件中引用子组件并定义ref

<v-food ref="selectfood"></v-food>

调用定义在子组件中的方法show

this.$refs.selectfood.show();//同时也可以调用子组件中的属性

vue中setTimeout的使用

在vue中使用setTimeout或者setInterval,如果按照在原来js的中方法,如

setTimeout(function(){
    this.isFlag = true;
},3000);

会发现data中定义的变量isFlag是获取不到的;解决方法如下:

  • 用setTimeout通过es6语法,setInterval也是一样

import { setTimeout } from "timers";
<script>
export default{
   data(){
     return {
       time:"",
       isFlag:false
     }
   },
   methods:{
     add(){
           clearTimeout(this.time);
           this.time = setTimeout(() =>{  
	       this.isFlag = true;
           },2000)
      }
   }
}
</script>

  • 定义外部self来代替全局this

 methods:{
	add(){
	   let self = this;
	   clearTimeout(this.time);
	   this.time = setTimeout(function(){
	      self.isFlag = true;
	   },2000)
	}
}

我们会发现利用例子的第一种方法,使用this来获取变量,会报错。这就是老生常谈的javaScript 的this 的问题。
因为用的一个function(){} 这里的 独立的作用域 this指向了全局(这里是window)而且window里没有myFunc这个函数,所报了错。 
使用es6的->写法,this继承外部对象,this指向为vue实例,即(new Vue);

监听鼠标滚动事件,实现头部悬浮效果

$nextTick 是在下次 DOM 更新循环结束之后执行延迟回调,鼠标滚动事件需要通过window.addEventListener("scroll",'')进行监听。

<script>
   mounted(){ 
      // 监听滚动事件
      this.$nextTick(function () {
	  window.addEventListener('scroll', this.needToTop);  //滚动事件监听
      });
   },
   methods:{
     needToTop(){
	let curHeight = document.documentElement.scrollTop || document.body.scrollTop; // 滚动条距离顶部的距离
	let bgareaHeight = this.$refs["bgarea"].offsetHeight; // 背景总高度
	let opacity = curHeight/bgareaHeight;
	this.$refs["title"].style.background = "rgba(255, 255, 255, "+opacity+")";
	this.$refs["title"].style.boxShadow = "0 0 .27rem rgba(204, 204, 204, "+opacity+")";
     }
   }
 </script>

vue上传图像

通过new FormData(),创建form对象,通过append向form对象添加数据。

html代码如下:

<div class="txarea">
   <input type="file" class="txfile" name="file" id="upimg" accept="image/*" @change="fileChange($event)">
   <p class="tx" @click="chooseType">点击上传头像</p>
</div>
<script>
export default{
methods:{
 // 获取用户图像
chooseType() {
   document.getElementById('upimg').click();
},
fileChange(e) {
  let file = e.target.files[0];     
  let param = new FormData(); //创建form对象
  param.append('file',file,file.name);//通过append向form对象添加数据
  
  let config = {
     headers:{'Content-Type':'multipart/form-data'}  //添加请求头
  };  
  this.axios.post(uploadUrl,param,config)
  .then(response=>{
     // 已经获取到图片地址,再调接口,保存到数据库即可;
     let reqData = {
 	phone: this.loginInfo.phone,
	pic:response.data.url   // 大图地址
     }
     this.setUserInfo(reqData);
   }) 
},
setUserInfo(){ // 保存用户图像
   ...
}
}
}
</script>

vue,@click="event()",添加()与不添加()的区别

应该是 Vue 对函数调用表达式额外用了一个函数做了层包装。
加与不加括号的区别在于事件对象参数 event 的处理。

不加括号时,函数第一个参数默认为 event;加了括号后,需要手动传入 $event 才能获得事件对象。

<template>
    <div class="btn-item">
        <button class="btn btn-success" @click="sure($event)">确定</button>
        <button class="btn btn-default" @click="quit">取消</button>
    </div>
</template>

<script>
  export default{
      name:'test',
      data(){
          return {

          }
      },
      methods:{
          sure(e){
               console.log(e.target);
          },
          quit(e){
              console.log(e.target);
          }
      }
  }
</script>

H5,设置textarea高度随文字输入增高;

在发表文字相关的业务需求中,当我们给textarea设置了固定高度,多余的内容就会被隐藏在里面,体验感不是很好;如下图,进行相关的设置,可以实现textarea高度自增;
<template>
  <textarea class="textArea" ref="textArea"  placeholder="输入正文" v-model="postList.content" @input="setPostContent"></textarea></template>
mounted(){  
  this.$nextTick(() => {        
    let textarea = document.querySelector('.textArea');        
    this.makeExpandingArea(textarea);     
  });  
}, 
 methods:{    
   setPostContent(){ // 设置正文内容       
     this.$refs.textArea.style.color = '#666666';      
   },   
  makeExpandingArea(el) {       
     var setStyle = function(el) {          
       el.style.height = 'auto';             
       el.style.height = el.scrollHeight + 'px';       
     }      
     var delayedResize = function(el) {           
        window.setTimeout(function() {              
           setStyle(el)               
         }, 0);        
     }          
  if (el.addEventListener) {             
     el.addEventListener('input',function() {                 
      setStyle(el)},false);             
      setStyle(el)      
      } else if (el.attachEvent) {        
           el.attachEvent('onpropertychange',function() { setStyle(el)           
       });               
      setStyle(el)          
  }          
  if (window.VBArray && window.addEventListener) { //IE9          
      el.attachEvent("onkeydown",function() {                
      var key = window.event.keyCode;                 
      if (key == 8 || key == 46) delayedResize(el); });             
          el.attachEvent("oncut",function() {           
              delayedResize(el);              
          }); //处理粘贴           
     }     
  }  

vue,监听滚动条滚动到最底部,加载下一页数据;

我遇到的一个需求是帖子在下拉到底部时,实现加载第二页数据;开始用的better-scroll插件,但是这个插件会自动给页面增加一个滑动层,导致帖子内容无法复制;所以,就可以用判断滚动条距离底部的距离的方法,实现数据加载。postDetail为帖子内容区域;_getPostCommentList()为加载数据的接口方法;代码如下:

 mounted() {    this.$nextTick(() => {       document.getElementById("postDetail").onscroll = this.scrollBottom;    }); }, methods:{   scrollBottom() {            // 获取 滚动高度 滚动距离 当前屏幕高度            let scrollHeight = document.getElementById("postDetail").scrollHeight,                scrollTop = document.getElementById("postDetail").scrollTop,                clientHeight = this.getClientHeight();            // 获取离底部的距离            let bottomHeight = scrollHeight - scrollTop - clientHeight;            // 传送滚动到sendComments 组件            this.bottomHeight = scrollTop;            // 如果距离底部小于5 请求数据            if (bottomHeight < 5) {                this.pageNo++;                if (this.totalPage >= this.pageNo) {                    // 说明还有更多的数据                    this.loadings = true;                    this._getPostCommentList(); // 分页获取评论数据;回复完评论,滚动条会自动到最底部,所以会加载第二页的数据;                } else {                    this.loadings = false;                    this.loadingOver = true;                }            }        }}  




项目实践:基于vue2.0 +vuex+ element-ui后台管理系统

后面会更新第二篇文章:

第二篇文章如下:干货分享:vue2.0做移动端开发用到的相关插件和经验总结(2)

  • VUX - Vue 移动端 UI 组件库的使用;
  • vue-lazyload :一个简单易用的 Vue 图片延迟加载插件;
  • vuex:vue状态管理工具详细入门;
  • async/await:异步神器来封装接口请求文件fetch.js;
  • vue 项目中的迭代判断技巧;
  • vue 项目中常用的图片引入方式;
  • 微信api在vue项目中的使用:
    1. vue2实现微信分享坑点和经验 ;
    2. vue2实现微信支付坑点和经验;
  • 百度地图api在vue项目中的使用:

    1. vue2.0项目中如何使用百度地图api

    2. vue2如何给地图添加房源覆盖物;

    3. 如何给地图添加自定义定位控件并更换控件的图标;

    4. 如何给地图添加自定义当前位置定位标注

    5. 几个常用的api(地图缩放,拖拽,获取当前位置)等功能的实现;

欢迎加入讨论组,一起来学习用vue,vuex,element,express,mongodb来构建后台管理系统;

一起来用项目实战加深自己对知识的理解。