“cssrem.rootFontSize”: root font-size (unit: px), 默认为: 16;
“cssrem.fixedDigits”: px转rem小数点最大长度,默认:6;
“cssrem.autoRemovePrefixZero”:自动移除0开头的前缀,默认:true;复制代码
项目中配置:
css
"cssrem.fixedDigits": 2,//px转化为rem保留2位小数
"cssrem.rootFontSize":75//px转化为rem基准复制代码
lib-flexible为移动端弹性布局适配解决方案。不少的大公司,如网易,淘宝等,都在用它做为移动端布局。html
npm install lib-flexible --save复制代码
import 'lib-flexible'复制代码
vue-touch其实封装了 hammer.js的方法,针对触屏的6大事件进行监听。官网。前端
npm install vue-touch@next复制代码
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的按压事件)复制代码
swiperleft: function () {
this.$router.push({'path':'/queuehistory'});
}复制代码
vee-validate为适用于vue项目中表单验证插件.引入vee-validate,会更加方便咱们进行表单验证。 官方网址.vue
npm install vee-validate@next --save
复制代码
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>复制代码
安装方法java
npm install --save better-scroll;
复制代码
<div class="wrapper">
<ul class="content">
<li>...</li>
<li>...</li>
...
</ul>
<!-- 这里能够放一些其它的 DOM,但不会影响滚动 -->
</div>复制代码
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();
}
});
}
}
}
复制代码
移动端项目中,在某些机型某些浏览器下,存在click事件300ms延迟的问题,影响用户满意度。缘由是:从点击屏幕上的元素到触发元素的 click 事件,移动浏览器会有大约 300 毫秒的等待时间,由于它想看看你是否是要进行双击(double tap)操做。webpack
vue项目中,能够经过引入fastclick第三方依赖包来解决。
ios
安装方法:git
npm install --save fastclick
复制代码
使用方法:es6
在main.js中
github
import fastclick from 'fastclick'
fastclick.attach(document.body)
复制代码
也能够直接下载fastclick.js,在相应页面直接引用。
移动端项目,因为在移动端没法打开控制台,因此没法像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信息了;
在平时项目的开发环境中,常常会遇到跨域的问题,尤为是使用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
}
}
复制代码
/**父组件代码:**/
<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>复制代码
子组件向父组件传递分为两种类型。
一、子组件改变父组件传递的props(你会发现经过props中的Object类型参数传输数据,能够经过子组件改变数据内容。这种方式是可行的,可是不推荐使用,由于官方定义prop是单向绑定);
二、经过$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;复制代码
this.bus.$emit("toChangeTitle","首页");
复制代码
mounted(){
this.bus.$on('toChangeTitle', function (title) {
console.log(title)
})
}复制代码
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或者setInterval,若是按照在原来js的中方法,如
setTimeout(function(){
this.isFlag = true;
},3000);
复制代码
会发现data中定义的变量isFlag是获取不到的;解决方法以下:
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>复制代码
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>
复制代码
经过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 对函数调用表达式额外用了一个函数作了层包装。
加与不加括号的区别在于事件对象参数 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>复制代码
<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);
}); //处理粘贴
}
}
复制代码
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)
百度地图api在vue项目中的使用:
vue2.0项目中如何使用百度地图api
vue2如何给地图添加房源覆盖物;
如何给地图添加自定义定位控件并更换控件的图标;
如何给地图添加自定义当前位置定位标注
几个经常使用的api(地图缩放,拖拽,获取当前位置)等功能的实现;
欢迎加入讨论组,一块儿来学习用vue,vuex,element,express,mongodb来构建后台管理系统;
一块儿来用项目实战加深本身对知识的理解。