
记录个人从 0 开始使用
mpvue开发小程序项目中踩到的坑
这个文档只是记录个人开发时遇到的坑,并不是非常专业,希望能对各位读者带来一些帮助,减少遇到相同问题时查找资料消耗的时间成本
1. 文件目录
// 文件目录
build
├------- build.js
├----- check-version.js
······
└----- webpack.prod.config.js
config
├----- dev.env.js
├----- index.js
└----- prod.env.js
dist // 打包后的小程序代码文件夹
|
·····
|
src
├----- commponents // 组件
| └----- card.vue
├----- pages
| └----- index // 页面文件夹
| ├----- index.vue // main.wxml & index.vue.wxml & main.wxss
| ├----- main.json // main.json
| └----- main.js // main.js
├----- app.json // 路由配置
├----- App.vue // app.wxss & app.wxml
├----- main.js // app.js
├----- static // 静态资源
| ├----- images
| └----- tabs
·····
└----- project.config.json // 小程序配置文件
2. 异常 bug 已找到解决方案
<template>
<div class="login">
<div class="input-group flex">
<div class="input-row flex-item">
<input
type="number"
maxlength="11"
class="block"
placeholder="登录帐号"
v-model="account.value"
@blur="hideClear('account')"
@focus="handleShowClear('account')"
@input="handleShowClear('account')"
>
<div
class="clear"
v-show="account.is_clear"
@tap="clearInput('account')"
>
<img src="/static/icons/icons_chongzhi@2x.png">
</div>
</div>
</div>
<div class="input-group flex">
<div class="input-row flex-item">
<input
type="text"
class="block"
placeholder="验证码"
v-model="password.value"
@blur="hideClear('password')"
@focus="handleShowClear('password')"
@input="handleShowClear('password')"
>
<div
class="clear"
v-show="password.is_clear"
@tap="clearInput('password')"
>
<img src="/static/icons/icons_chongzhi@2x.png">
</div>
</div>
<div class="input-row get-vertifly" @click="timeCountDown">
<span>获取验证码</span>
</div>
</div>
<button class="login-btn">登录</button>
</div>
</template>
<script>
export default {
data() {
// 如果 data 内对象层级太深会造成一个无法更新数据的bug
return {
// 如果在该格式的情况 methods 中的方法修改 data 将不会同步
// 并且 console 打印的调试结果会很奇怪
// form: {
// account: {
// value: '',
// is_clear: false
// },
// password: {
// value: '',
// is_clear: false
// },
// },
account: {
value: '',
is_clear: false
},
password: {
value: '',
is_clear: false
},
timer: null,
timeCount: 60,
text: defaultText,
isAjax: false,
}
},
methods: {
// 隐藏 clear 图标
hideClear(type) {
this[type].is_clear = false
},
// 显示 clear 图标
handleShowClear(type) {
let $that = this[type]
let is_clear;
if ($that.value) {
is_clear = true
} else {
is_clear = false
}
// 该判断减少 data 数据修改次数,减少性能消耗
if ($that.is_clear !== is_clear) {
this[type].is_clear = is_clear
}
// 下面这句将会失效
// this.form[type].is_clear = is_clear
// 以下是执行上方注释的代码之后的打印结果
// 怪异的表现,感觉像是修改成功之后又修改回去了
// console.log(this.form.account) // { __ob__ } => { value: '', is_clear: false }
// console.log(JSON.stringify(this.form.account)) // "{ 'value': '', 'is_clear': true }"
},
// 清空对应输入框
clearInput(type) {
this[type].value = '';
},
}
}
</script>
<style>
/**
* 在 css 中无法使用 background-image 属性,
* 编译成小程序代码之后将会找不到对应文件图片,查看编译后的代码会看到一串奇怪的路径
*/
.login {
margin-top: .7rem;
padding: 0 .56rem;
}
.input-group {
border-bottom: 1px solid #d8d8d8;
line-height: .56rem;
margin-bottom: .28rem;
}
.input-group .input-row {
position: relative;
padding: .3rem 0;
}
.input-row .clear {
position: absolute;
top: 0;
right: 6rpx;
bottom: 0;
margin: auto 0;
width: .36rem;
height: .36rem;
font-size: 0;
line-height: 0;
z-index: 3;
}
.clear img {
display: block;
width: 100%;
height: 100%;
}
.input-row input {
font-size: .4rem;
}
.get-vertifly{
font-size: .28rem;
color: #888;
width: 2rem;
text-align: center;
}
.login-btn {
margin: .6rem .2rem 0;
line-height: .88rem;
height: .88rem;
background: linear-gradient(90deg,#f22320 0%,#ff5b79 100%);
box-shadow: 0 5px 8px 0 #ee0809;
border-radius: .56rem;
font-size: .34rem;
color: #fff;
font-weight: 500;
}
</style>
3. 如何导入外部 css 文件
// 在 scr 文件夹新建一个 app.css 文件
// 打开要导入 css 的 .vue 文件,比如:App.vue
<script>
// 可多尝试几种导入方式,'@/src/app.css' 的导入方式还未尝试过,未知结果如何
import './app.css'
export default {
data() {
return {
// code
}
}
}
</script>
4. 在项目内使用 fly 或 axios
- 使用
flyio
先安装模块npm install flyiooryarn add flyio
开始配置:// 打开 ...\build\webpack.base.conf.js 文件 alias: { 'vue': 'mpvue', '@': resolve('src') // 新增该配置只是为了方便引入 flyio 模块, 末尾的 wx 表示引入的是小程序相关模块 'wxFly': 'flyio/dist/npm/wx' }// 在 src 目录下新建 fly.js 文件 import wxFly from 'wxFly' // 这里的 wxFly 是之前在 alias 自定义的模块名称 // const Fly = require("flyio/dist/npm/wx"); // 也可以用 require 导入模块 const fly = new wxFly() // 实例化 flyio const url = 'http://xxx.xxx.com/xxx/xx' //添加拦截器 fly.interceptors.request.use((config,promise)=>{ // 给所有请求添加自定义header // code return config; }) //添加响应拦截器,响应拦截器会在then/catch处理之前执行 fly.interceptors.response.use( (response) => { if (response.status === 200) { // 只将请求结果的data字段返回 return response.data } else { } }, (err) => { //发生网络错误后会走到这里 } ) fly.config.baseURL = url export default fly// 打开 src/main.js import Vue from 'vue' import App from './App' import './app.css' // 这里可以顺便导入全局 css import fly from './fly.js' // 导入之前配置的 fly 文件 Vue.config.productionTip = false App.mpType = 'app' const app = new Vue(App) app.$mount() Vue.prototype.$http = fly // 最好在 app.$mount() 代码之后将 fly 挂载到 Vue 原型 - 使用
axios
老规矩, 安装模块npm install axiosoryarn add axios
配置方式和flyio类似, 只需要查api按照文档做自定义配置就好// 唯一的差异在 ...\build\webpack.base.conf.js 文件 alias: { // ... 'axios': 'axios/dist/axios' }
5. 使用小程序内的全局变量 globalData
查了一下资料, 有文章说使用 `this.$root.$mp.app`, 有可能是版本原因, mpvue 的过去版本可能可以实现吧. 该方式实现的全局变量在执行小程序路由方法跳转 `page` 之后就获取不到之前缓存的数据了. 想做到在整个项目中都能自由获取的全局变量用以下实现就好.
如果是大型项目需求全局变量的话建议使用 Vuex, 以下方式只适用于小项目
// ./src/main.js 文件
app.$mount()
// 一定要放在 app.$mount() 代码之下, 不然 webpack 自动编译不会动过, 会抛出错误
// 查了很多文章, 只说了要在 const app = new Vue(App) 代码之下, 可能版本的原因, 之前查的资料可能对应 mpvue 老版本适用吧
Vue.prototype.globalData = getApp().globalData // 将 globalData 挂载给 Vue 原型
// 挂载给 Vue 原型之后使用如下代码就可调用与配置了
// this.globalData.xxx = xxx
6. 小程序 page 之间的传参
// 小程序相关的方法都在 mpvue 这个全局变量
let url = '../setting/main?id=xxx'
mpvue.navigateTo({ url })
// 在 setting.vue 文件内
console.log(this.$root.$mp.query) // => { id: 'xxx' }
写在最后
这是本人目前使用 mpvue 中的所有相关依赖, 该文章内所有相关配置只适用下面的依赖配置版本, 其它版本暂未试过, 各位读者可自行测试
"dependencies": {
"flyio": "^0.6.14",
"mpvue": "^2.0.0"
},
"devDependencies": {
"babel-core": "^6.22.1",
"babel-loader": "^7.1.1",
"babel-plugin-transform-runtime": "^6.22.0",
"babel-preset-env": "^1.3.2",
"babel-preset-stage-2": "^6.22.0",
"babel-register": "^6.22.0",
"chalk": "^2.4.0",
"connect-history-api-fallback": "^1.3.0",
"copy-webpack-plugin": "^4.5.1",
"css-loader": "^0.28.11",
"cssnano": "^3.10.0",
"eventsource-polyfill": "^0.9.6",
"express": "^4.16.3",
"extract-text-webpack-plugin": "^3.0.2",
"file-loader": "^1.1.11",
"friendly-errors-webpack-plugin": "^1.7.0",
"glob": "^7.1.2",
"html-webpack-plugin": "^3.2.0",
"http-proxy-middleware": "^0.18.0",
"mkdirp": "^0.5.1",
"mpvue-loader": "^2.0.0",
"mpvue-template-compiler": "^2.0.0",
"mpvue-webpack-target": "^1.0.3",
"optimize-css-assets-webpack-plugin": "^3.2.0",
"ora": "^2.0.0",
"portfinder": "^1.0.13",
"postcss-loader": "^2.1.4",
"postcss-mpvue-wxss": "^1.0.0",
"prettier": "~1.12.1",
"px2rpx-loader": "^0.1.10",
"relative": "^3.0.2",
"rimraf": "^2.6.0",
"semver": "^5.3.0",
"shelljs": "^0.8.1",
"uglifyjs-webpack-plugin": "^1.2.5",
"url-loader": "^1.0.1",
"vue-style-loader": "^4.1.0",
"webpack": "^3.11.0",
"webpack-bundle-analyzer": "^2.2.1",
"webpack-dev-middleware-hard-disk": "^1.12.0",
"webpack-merge": "^4.1.0",
"webpack-mpvue-asset-plugin": "^2.0.0",
"webpack-mpvue-vendor-plugin": "^2.0.0"
},
未完待续...