最近在用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()",添加()与不添加()的区别;
1、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; "css.remoteStyleSheets": []
项目中配置:
“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”,将自己的设置放入右边覆盖“默认设置”,重启编辑器,即可,如图:
2、lib-flexible
介绍:lib-flexible为移动端弹性布局适配解决方案。很多的大公司,如网易,淘宝等,都在用它作为移动端布局。
使用方法:
- 安装lib-flexible:
npm install lib-flexible --save
- 引入lib-flexible,在项目入口文件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有可能是固定的了
知识延伸:
px2rem-loader,在做像素单位适配的时,你也可以不用安装cssrem,直接用px,我们可以通过安装插件:px2rem-loader并进行相应的配置,通过编译之后,自动将px转换为rem;
使用方法,可参考官网;但是其有一定的局限性,即只能将.vue文件style标签中的px转成rem,对外部引入css,px2rem能不能转换rem问题;
对于引入了第三方框架,他们的样式是另一套写法,样式会被flexible转换,就会破坏框架的样式。
如果在.vue文件style中的某一行代码不希望被转成rem,只要在后面写上注释 /* no*/就可以了。
3、vue-touch
官网:https://github.com/vuejs/vue-touch/tree/next
介绍: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'})
使用实例:
<v-touch v-on:swipeleft="onSwipeLeft(data)">Swipe me!</v-touch> //左划 默认渲染为div data为参数
<v-touch tag="a" v-on:tap="onTap">Tap me!</v-touch> //点击 渲染为一个a标签
<v-touch tag="p" v-on:tap="onTap">Tap me!</v-touch> //点击 渲染为p标签
常用的事件有: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兼容;
应用实例:
(2)、通过手势滑动,进行页面的切换,如:
swiperleft: function () { this.$router.push({'path':'/queuehistory'}); },
4、vee-validate
- vee-validate介绍:
vee-validate为适用于vue项目中表单验证插件.引入vee-validate,会更加方便我们进行表单验证。 官方网址.
- 安装vee-validate
npm install vee-validate@next --save
注意:@next,不然是Vue1.0版本
- 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)
- 组件中使用
<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>
5、better-scroll
- better-scroll介绍:
- 使用方法
安装方法
npm install --save better-scroll;
起步
<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)
结合接口下拉刷新加载更多数据
6、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,在相应页面直接引用。
7、手机前端开发调试利器 – 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信息了;
8、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 } }
9、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方法来响应事件。
- 非父子组件传递数据;
通过使用一个空的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) }) }
10、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();//同时也可以调用子组件中的属性。
11、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);
12、监听鼠标滚动事件,实现头部悬浮效果
$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>
13、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>
14、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>
项目实践:基于vue2.0 +vuex+ element-ui后台管理系统
后面会更新第二篇文章:
- VUX - Vue 移动端 UI 组件库的使用;
- vuex:vue状态管理工具详细入门;
- 百度地图api在vue项目中的使用:
- vue2如何给地图添加房源覆盖物;
- 如何给地图添加自定义定位控件并更换控件的图标;
- 几个常用的api(地图缩放,拖拽,获取当前位置)等功能的实现;
- 微信api在vue项目中的使用:
- vue2实现微信分享坑点和经验 ;
- vue2实现微信支付坑点和经验;
- fetch封装接口的统一管理;
你的关注和支持是对我最大的动力~
书山有路群[一个非常活跃的读书分享群,每周都有新书分享]:452450927
微博:http://weibo.com/u/2241641312
出处:http://www.cnblogs.com/wdlhao/
github:https://github.com/wdlhao