webpack代码分割和懒加载

单页面处理代码分割

引入第三方依赖

在页面引入中进行修改

1
2
3
4
5
6
// import * as _ from 'lodash'
修改为
require.ensure(['lodash'], function() {
var _ = require('lodash') // 注意,这里一定要require,上面的require不会真正的引入
_.join(['1','2'], '3')
}, 'vendor') //这里是指定的chunkName

判断引入模块

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
在pageA里面修改代码
page = 'subpageA'

if (page === 'subpageA') {
require.ensure(['./subPageA'], function() {
var subpageA = require('./subPageA')
}, 'subPageA')
}else {
require.ensure(['./subPageB'], function() {
var subpageA = require('./subPageB')
}, 'subPageB')
}

// import './subPageA'
// import './subPageB'

// 分离页面代码和第三方依赖
require.ensure(['lodash'], function() {
var _ = require('lodash')
_.join(['1','2'],'3')
},'vendor')
// import * as _ from 'lodash'
export default 'PageA'

抽离公共代码块modulesA

1
2
3
4
5
6
7
8
9
10
11
12
13
因为modulesA代码是同时被subpageA和subpageB页面引入的,在pageA页面中,我们有进行判断是引入subpageA还是subPageB页面,所以我们直接
在pageA里面直接引入moduleA
require.include('./moduleA')

这样进行打包的时候,我们在subPageA和subPageB的包里面就没有modelA的代码,而是放在了common里面了
这里需要在webpack.config.js里面进行配置
new webpack.optimize.CommonsChunkPlugin({
name: 'common',
minChunks: 2,
chunks: ['pageA', 'pageB']
}),

如果没有进行配置optimeze插件的话,moduleA里面的代码会被打包到pageA代码里面

动态import 和 require.ensure不一样的地方:

import 引入后直接就执行了

动态import

1
2
3
4
5
6
7
8
9
10
11
12
13
14
if (page === 'subpageA') {
// require.ensure(['./subPageA'], function() {
// var subpageA = require('./subPageA')
// }, 'subPageA')
import('./subPageA').then(function(subPageA) {
console.log(subPageA)
})
}

如果不指定chunkName, 会打包成1/2等类型的chunkName
在动态import中指定chunkName 需要用到魔法注释
import(/* webpackChunkName: 'subPageA' */ './subPageA').then(function(data) {
console.log(data)
})

async

这个有什么用?,如果是多entry进行打包的话,是把公共模块的代码打包出来–不用指定哪个模块引用了公共模块了

1
2
3
4
5
6
7
plugins: [
new webpack.optimize.CommonsChunkPlugin({
async: 'async-common', 指定打包的chunkname
children: true, 注意这个属性不可以和chunk等一些属性共用(具体自行百度)
minChunks:2
})
]

babel编译

#1. 下载依赖包

1
2
3
4
5
6
"dependencies": {
"@babel/core": "^7.2.2",
"babel-core": "^6.26.3",
"babel-loader": "^8.0.5",
"@babel/preset-env": "^7.3.4"
},

需要注意的是, Babel默认只转换新的javascript语法,而不转换新的API,比如

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
babel不会对 :
Generator
Set
Map
Array.from
Array.prototype.includes
进行转义,如果需要,要安装全局或者局部垫片进行处理
局部垫片 babel-plugin-transform-runtime babel-runtime -save-dev


全局垫片 babel-polyfill -使用方案
在入口文件直接 import 'babel-polyfill'即可,如果打包文件没有进行配置的话,在全局创建.babelrc文件进行配置(在Babel执行编译的过程中,会从项目的根目录下的 .babelrc文件中读取配置。.babelrc是一个json格式的文件。)
{
"presets" : [
["@babel/preset-env", {
"targets": {
"browsers": ["last 2 versions"]
}
}]
],
"plugins": ["transform-runtime"] // 如果使用局部垫片改变api的话进行配置
}

如果出现this.setDynamic is not a function ,检查@babel/core/babel-loader和runtime 和transform的版本是否对应

2.配置输出

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
module.exports = {
entry : {
appTest: './app.js'
},
output : {
// filename: '[name].[hash:5].js'
filename: '[name].js'
},
module: {
rules: [
{
test: /\.js$/,
use:{
loader: 'babel-loader',
options: {
presets: [
['@babel/preset-env', {
targets: {
browsers: ['>1%', 'last 2 versions']
}
}]
]
}
},
exclude: '/node_modules/'
}
]
}
}

参考链接https://www.cnblogs.com/tugenhua0707/p/9452471.html

vue操作日志

#webpack有4个重点内容:

  • 入口(entry)
  • 输出(output)
  • 加载器(loader)
  • 插件(plugins)

我们的vue项目都是从根目录下的index.html文件开始执行的,因为我们在dev.conf.js文件的plugin配置中设置了起始位置是index.html

在base.conf.js文件的module.exports中,我们配置了入口文件是main.js,所以我们在main.js文件中,配置了vue实例,router对象, 在new一个实例化对象时

1
2
3
4
5
6
new Vue({
el: '#first', 这里的对象就是index.html里面的id选择器
router, 必须配置router才可以进行单页渲染
components: { Page }, 组件引入
template: '<Page/>' 组件模块, 有另外一种写法,使用render函数 render: h => h(App)
})

watch用于异步操作,而computed同步

这二个里面尽量不要去修改,只能去显示,否则会造成无限循环的情况 –> 因为如果是修改的话,就又触发了监听事件。

监听事件,可以监听对象的属性,写法是

1
2
3
4
5
6
7
8
9
watch: {
'firstName.a': { 使用字符串的形式
handler (newName, oldName) {
this.fullName = newName + '12'
}, 监听会先触发handler函数, 可以利用这点实现三层互动,一个区域实现二层互动,不干扰的情况
immediate: true
// deep: true 不用字符串监听属性的话,就必须使用deep,---耗性能
}
},

props组件件传值可以通过type进行控制传值类型

子组件向父组件传递参数

子组件也需要设定参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<template>
<div class="son">
Hi,Every Bady
<p><input type="text" @input="handleInput"></p>
</div>
</template>
<script>
export default {
name: 'son',
props: ['value'], 子组件设定传值信息
methods: {
handleInput (e) {
this.$emit('input', e.target.value) emit函数--一个事件名称,一个要传递的值
}
}
}
还可以这样写
export default {
name: 'son',
model: {
prop: 'value1',
envent: 'input'
},
methods: {
handleInput (e) {
this.$emit('input', e.target.value) emit函数--一个事件名称,一个要传递的值
}
}
}
</script>

父组件也需要在data里面,设置,并在子组件里书写

1
2
<son  v-model="value"></son>  二者等同
<son :value="value" @input = "value = arguments[0]">

ssh操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
ssh-key
ssh-keygen.exe -t rsa -C "账号地址"

生成的秘钥在用户的.ssh文件夹里

创建分支
PS D:\work\test> git checkout -b feature
Switched to a new branch 'feature'
PS D:\work\test> git pull origin feature

git pull origin feature

git status
git add .
git commit -m 'xxx'

git push origin feature

git checkout -b product 切换product分支

修改本地数据库后需要执行 php .\artisan config:clear

计算属性

computed:{
  usrInfo(){
    var usrInfo = this.$store.state.usrInfo;
    return usrInfo;
  }
}

computed: mapState([
  // 映射 this.count 为 store.state.count
  'count'
])

store.state.stateA   拿取state
store.dispatch    触发action里的函数
通过 commit  触发 mutations 里的函数

展开运算符

1
2
3
function test(a,b,c) { }
var args = [0,1,2];
test(...args)

vue的条件判断

1
2
3
4
<div class="app-wrapper" :class="{hideSidebar:!sidebar.opened}">
:class="{hideSidebar: false}" 如果值为false hideSidebar类不会出现,如果为true,则在class添加 hideSidebar类

如果a.b本身不存在, 你在methods更新的时候,需要使用 this.$set(a,b,val)

报错信息

1
2
Duplicate keys detected: 'App'. This may cause an update error.
出现2个相同的key值会报此种错误

判断上传文件类型的写法

1
2
<input type="file" accept="image/*">  可以上传所有文件
或者指定 accept="image/jpg,image/png"

多段判断分析

1
2
3
i==3? 'so' : b==5 ?  '66' : '88'
如果i==3 那么肯定输出3
如果 i!=3 那么判断b是否等于5,如果等于5,输出66,否则输出88

路由守卫使用vuex

路由守卫,当触发路由时,会先执行这个函数,to-到哪里去,from-从哪里来,next,第三个参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
beforeRouteEnter(to, from, next) {
这里的record是暴露出去的一个对象,里面 有个get函数
export const record = {
get(data) {
return new Ajax({
url: '/admin/record/getRecordList',
method: 'get',
params: data
})
}
}


record.get(to.query).then(data => {
console.log(data)
next(vm => {
这里的vm就是当前的实例化对象,this
vm.tableData = data.items;
vm.total = parseInt(data.total);
vm.query.page = data.page;
vm.query.pageSize = data.pageSize;
vm.totalAmount = data.extra.sum;
})
})
}

beforeRouteUpdate(to,from,next){
console.log('beforeRouteUpdate')
next()
}

beforeRouteUpdate(to,from,next)

About组件是有二级导航的,在切换二级导航的时候,对应的内容是在变化的;但是about组件是复用的,只会生成一次,切换二级导航的时,如何知道导航在更新呢?

一个组件有二级导航的时候,点击二级导航的时候导航路径更新了,会触发路由钩子函数beforeRouteUpdate。

还有一个beforeRouteLeave(to,from,next)

###

Vue中动态类名的实现

  1. 1
    2
    3
    4
    5
    6
    1. 第一种方式:对象的形式 -->
    <!-- 第一个参数 类名, 第二个参数:boolean值 --> true就显示 :
    2. 第二种方式:三元表达式 注意点:放在数组中,类名要用引号
    <p :class="[ 1 < 2 ? 'p1' : 'p' ]" >三元表示式(文字的颜色)</p>

    在dom元素上添加ref='cc' 后面我们可以通过this.$refs.cc拿到该dom元素

打印报表的实现

引入import { parseTime } from ‘@/utils’
2.tHeader 是props信息 list是数据源
handleDownload() {
import(‘@/vendor/Export2Excel’).then(excel => {
const tHeader = [‘data’, ‘name’, ‘address’, ‘name’]
const filterVal = [‘date’, ‘name’, ‘address’, ‘name’]
const list = this.tableData
const data = this.formatJson(filterVal, list)
const date = new Date();
const filename = date.toLocaleString().split(‘ ‘)[0]+’_’+date.getTime()+’’
excel.export_json_to_excel(tHeader, data, filename)
})
},
formatJson(filterVal, jsonData) {
return jsonData.map(v => filterVal.map(j => {
if(j === ‘timestamp’) {
return parseTime(v[j])
}else {
return v[j]
}
}))
},

echarts转换base64的方法

1
2
3
4
5
cgImgBase64 = myChart.getDataURL();
setTimeout(() => {
let baseImg = myChart.getDataURL()
this.printSrc = baseImg;
}, 2000)
form表单的提交有个浏览器的默认刷新行为,把form标签改成div就没事了

一个vue页面使用2个style标签!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
### 

<style lang="scss" scoped>
html{font-size: 16px;}
.singleListAd{height: 6rem;}
.listMain{height: 24rem;}
</style>

我使用了2个style标签,一个使用了scoped属性,使其单一页面完成父元素的font-size值赋值,而不修改其他页面的父元素的size值


### 一个dom对象赋予2个事件绑定


@keyup.enter="searchList" @blur="searchList"

function random(len, start, end) {
  var arr = [];
  function _inner(start, end) {
    var span = end - start;
    return parseInt(Math.random() * span + start)
  }
  while (arr.length < len) {
    var num = _inner(start, end);
      if (arr.indexOf(num) == -1) {
        arr.push(num);
      }
    }
    return arr;
  }

var cc = [[1,2],[3,4]]

将多维数组降级到一维数组的方法

1
d2 = Array.prototype.concat.apply([], cc)

组件封装的注意点

1
2
1. 父组件传递给子组件的时候,父组件的data要定义属性,比如''   []  :子组件props = "父组件data"   注意,一定要加双引号
2. 分页数字,在父组件定义要写成nuber形式, 而子组件props里必须要''

vue组件设置样式的方法

​ updataList() {
​ let currentEle = this.$refs.singleList[0].clientHeight;
​ this.$refs.mainHeight.style.height = currentEle * 4.4 + ‘px’;
​ },

this.$nextTick(() => {
  this.updataList();
});
当dom元素渲染完成之后会触发这个方法

判断用户平台

<script type="text/javascript">
var ua = navigator.userAgent.toLowerCase();
var isWeixin = ua.indexOf('micromessenger') != -1;
var isAndroid = ua.indexOf('android') != -1;
var isIos = (ua.indexOf('iphone') != -1) || (ua.indexOf('ipad') != -1);
if (!isWeixin) {
    document.head.innerHTML = '
    <title>抱歉,出错了</title>
    <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=0">
            <link rel="stylesheet" type="text/css" href="https://res.wx.qq.com/open/libs/weui/0.4.1/weui.css">';
    document.body.innerHTML = '
                <div class="weui_msg">
                    <div class="weui_icon_area">
                        <i class="weui_icon_info weui_icon_msg"></i>
                    </div>
                    <div class="weui_text_area">
                        <h4 class="weui_msg_title">请在微信客户端打开链接</h4>
                    </div>
                </div>';
}

            </script>

封装的echarts组件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323

<template>
<div class="allCountShow" v-show="nowAll">
<div class="showInfo">
<span name="sToday" v-for="(item, key) in showSlot" :key="key">
{{item.explain}} : {{item.today}}
</span>
</div>
<div class="switch">
<span @click="showDataCount">数据统计</span>
<span @click="testFunction" :class="[showActive ? 'active' : '']">图表统计</span>
</div>
<!-- 表格所有 -->
<div class="tableBox" ref='c2' v-show="showData">
<template>
<el-table
:data="tableData"
border
style="width: 98%;text-align:'center';"
:header-cell-style='styleObj'>
<el-table-column v-for = "(item ,index) in tablePropList" :key = "index"
:prop="item.prop"
:label="item.label"
align="center">
</el-table-column>

</el-table>
</template>
<div class="report" style="margin-top:12px;">
<el-button class="no-print" type="success" size="medium" @click="handleDownload">导出excel报表</el-button>
<el-button class="no-print" type="success" @click='pringCharts' size="medium" >打印报表</el-button>
<el-button v-show="freeUpdataTime" type="default" class="updataTimeS" size="medium" ><div>数据统计更新时间: <span>{{updataTime}}</span></div></el-button>
</div>

<!-- 分页 -->
<template>
<div class="block pageNub no-print">
<el-pagination
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="currentPage4"
:page-sizes="[10, 20, 30, 40, 50, 100, 1000]"
:page-size="queryObj.pageSize"
layout="total, sizes, prev, pager, next, jumper"
:total="allPageSize">
</el-pagination>
</div>
</template>
</div>
<!-- 表格结束 -->
<!-- charts开始 -->
<div class="chartsBox" v-show="!showData">
<div id="main" ref='cc'>

</div>
<el-button v-show="printSrc != ''" @click="pringChartsTwo" type="success" size="medium" >打印图表</el-button>
</div>
</div>
</template>
<script>
import { parseTime } from '@/utils';
import Print from '@/api/print';
import Vue from 'vue';
Vue.use(Print);
var echarts = require('echarts');
export default {
props: {
kenTitle: '',
kenData: '',
kenParams: '',
tableData: '',
allPageSize: '',
queryObj: {},
showSlot: '',
tablePropList: '',
updataTime: '',
freeUpdataTime: ''
},
data() {
return {
printSrc: '',
test: 1,
showData: true,
showActive: 0,
styleObj: {
background: '#bcbcbc'
},
currentPage4: 1,
nowToday: false,
nowAll: true
};
},
methods: {
handleSizeChange(val) {
this.$emit('pageNubShow1', val)
},
handleCurrentChange(val) {
this.currentPage4 = val
this.$emit('currentPageSize', val)
},
handleDownload() {
var tHeaderArrShow = []
var filterValArrShow = []
let loopArrayDown = this.tablePropList
for(let i = 0; i<loopArrayDown.length; i++) {
if(typeof loopArrayDown[i] == 'object') {
tHeaderArrShow.push(loopArrayDown[i].prop)
filterValArrShow.push(loopArrayDown[i].label)
}
}
import('@/vendor/Export2Excel').then(excel => {
const tHeader = tHeaderArrShow;
const filterVal = tHeaderArrShow;
const list = this.tableData;
const data = this.formatJson(filterVal, list);
const date = new Date();
const filename =
date.toLocaleString().split(' ')[0] + '_' + date.getTime() + '';
excel.export_json_to_excel(tHeader, data, filename);
});
},
formatJson(filterVal, jsonData) {
return jsonData.map(v =>
filterVal.map(j => {
if(j === 'timestamp') {
return parseTime(v[j]);
}else {
return v[j];
}
})
);
},
showDataCount() {
this.showActive = 0;
this.showData = true;
},
// 打印报表功能实现
pringCharts() {
this.$print(this.$refs.c2);
},
pringChartsTwo() {
let imgSrcChange = this.printSrc
var imgDom = '<img src=\''+imgSrcChange+'\'>';
document.body.innerHTML = imgDom;
setTimeout(function() {
window.print()
}, 1000)
},
// 修改內容
testFunction() {
console.log(this.kenTitle)
let _this = this
let worldMapContainer = document.getElementById('main')
this.showActive = 1; // 点击图标按钮
this.showData = false; // 展示数据模块
var myChart = echarts.init(this.$refs.cc);
var resizeWorldMapContainer = function() {
worldMapContainer.style.width = window.innerWidth -400 + 'px';
// worldMapContainer.style.height = window.innerHeight + 'px';
worldMapContainer.style.height = 500 + 'px';
}
resizeWorldMapContainer()
// 指定图表的配置项和数据
let seriesData = [] // series的数据集合
let loopData = _this.kenData// 数据集合,数组对象
for(let i= 0; i< loopData.length; i++) {
let a = {}
a.name = _this.kenParams.one[i]
a.type = 'bar'
a.data = loopData[i]
a.itemStyle = {
normal: {
color: _this.kenParams.color[i] || ''
}
}
seriesData.push(a)
}
let echartsOption = {
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'shadow'
}
},
xAxis: [
{
type: 'category',
data: _this.kenTitle,
axisPointer: {
type: 'shadow'
},
axisLabel: {
interval: 0
}
}

],
legend: {
data: _this.kenParams.one,
bottom: '0%'
},
yAxis: [
{
type: 'value',
name: '数量',
min: 0,
max: _this.kenParams.interval[0],
interval: _this.kenParams.interval[1]
}
],
series: seriesData
}
myChart.setOption(echartsOption)
myChart.resize();
window.onresize = function() {
// 重置容器高宽
resizeWorldMapContainer();
myChart.resize();
};
setTimeout(() => {
let baseImg = myChart.getDataURL()
this.printSrc = baseImg;
}, 2000)
},
changeLoop() {
this.showActive = 0;
this.showData = true;
}
},
mounted() {
// this.showTable = this.tableData
// this.showSlot = this.slotList
}
};
</script>
<style scoped>
.showInfo{display:flex;}
.showInfo span{width: 14%;}
.el-input__prefix{right:5px}
.el-input__icon{float:right}
.showInfo{display: flex;padding-left:4%;line-height: 100px;border-bottom: 1px solid #ccc}
.showInfo span{margin-right:24px;}
.showInfo span{font-size: 18px;padding-left:12px;}
.switch{padding:0 16px;text-align: center;margin:0 auto;margin-top:10px;width:100%;display: inline-block;margin:20px 0;}
.switch span{display: inline-block;width: 80px;text-align: left;cursor: pointer;}
.switch span:last-child{text-align: center;padding-bottom:12px;}
.tableBox{margin-left:2%;}
.pageNub{text-align: center;margin-top:30px;}
.active{border-bottom: 1px solid #0094ff;}
.chartsBox{padding-left:4%;}
main{width: 600px;height:400px;}
.updataTimeS{cursor: default !important;}
</style>
<style>
.el-date-editor.el-input, .el-date-editor.el-input__inner{width: 156px;}
.el-input__inner{height: 32px;}
</style>








### 高德poi的使用

' ' '
html
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="initial-scale=1.0, user-scalable=no, width=device-width">
<title>输入提示</title>
<link rel="stylesheet" href="https://a.amap.com/jsapi_demos/static/demo-center/css/demo-center.css" />
<style>
html,
body,
#container {
width: 100%;
height: 100%;
}
</style>
</head>
<body>
<div id="container"></div>
<div class="info">
<div class="input-item">
<div class="input-item-prepend">
<span class="input-item-text" style="width:8rem;">请输入关键字</span>
</div>
<input id='tipinput' type="text">
</div>
</div>

<script type="text/javascript" src="https://webapi.amap.com/maps?v=1.4.10&key=0e290c2877e27fab87d0f6a3be962b0e&plugin=AMap.Autocomplete"></script>
<script type="text/javascript" src="https://cache.amap.com/lbs/static/addToolbar.js"></script>
<script type="text/javascript">
var map = new AMap.Map('container');
AMap.plugin('AMap.Autocomplete', function(){
// 实例化Autocomplete
var autoOptions = {
//city 限定城市,默认全国
city: '全国'
}
let input = document.querySelector('#tipinput')
let container1 = document.querySelector('#container')
container1.style.opacity = '0';
input.onkeyup = function(e){
let keyword = input.value
var autoComplete= new AMap.Autocomplete(autoOptions);
autoComplete.search(keyword, function(status, result) {
// 搜索成功时,result即是对应的匹配数据
console.log(result)
})
}
})
</script>
</body>
</html>
注意点: 要使用webjsapi 的key值 而不是web服务的key值

移动端常见代码

转换base64

mui(".uploadBtn")[0].onchange =function(){
            var reader = new FileReader();
            reader.onload = function(e) {    

// mui(‘.positive’)[0].src = reader.result
console.log(reader.result)
}

// console.log(this.files[0])
reader.readAsDataURL(this.files[0]);
}

let transReDetail = JSON.parse($(e.target).attr('data-transRep'))

验证模块
function dingxiangjiaoyi(){
let shuliang = $(‘.dingxiangNub’).val()
let adder = $(‘.dingxiangAdder’).val()
let dingxiangPwd = $(‘.dingxiangPwd’).val()
if(shuliang == “”){
mui.toast(‘数量不能为空’)
return
}
if(adder == “”){
mui.toast(‘地址不能为空’)
return
}
if(dingxiangPwd == “”){
mui.toast(‘密码不能为空’)
return
}
$.ajax({
url: apqurl +’’,
type: “post”,
success: function(dat){
console.log(dat)
}
})
}

基础模块
$(function(){
let token = get(‘mytoKen’)
init()
function init(){
getList()
}
function getList(){
$.ajax({
url: apqurl +’api/user/GetUserInfo?token=’+token,
type: “get”,
success: function(dat){
console.log(dat)
}
})
}
})

返回按键
mui(“body”).on(“tap”, “.back”, function() {
backFn(window);
});
function backFn(w) {
var ws = null;
if(w.plus) {
console.log(1)
ws || (ws = plus.webview.currentWebview());
ws.close(‘auto’);
plus.webview.getWebviewById(‘currencyExchange’).reload();

    } else if(history.length > 1) {
        console.log(3)
        history.back();
    } else {
        w.close();
    }
}

转换时间块

Date.prototype.Format = function(fmt) {
                       var o = {   
                           "M+" : this.getMonth()+1,                 //月份   
                           "d+" : this.getDate(),                    //日   
                           "h+" : this.getHours(),                   //小时   
                           "m+" : this.getMinutes(),                 //分   
                           "s+" : this.getSeconds(),                 //秒   
                           "q+" : Math.floor((this.getMonth()+3)/3), //季度   
                           "S"  : this.getMilliseconds()             //毫秒   
                       };   
                       if(/(y+)/.test(fmt))   
                           fmt=fmt.replace(RegExp.$1, (this.getFullYear()+"").substr(4 - RegExp.$1.length));   
                       for(var k in o)   
                           if(new RegExp("("+ k +")").test(fmt))   
                       fmt = fmt.replace(RegExp.$1, (RegExp.$1.length==1) ? (o[k]) : (("00"+ o[k]).substr((""+ o[k]).length)));   
                       return fmt;   
                   } 

let dingxiangHtml = template(‘dingxiangTmp’,{‘ken’:dat.data})
$(‘#dingxiangTab’).html(dingxiangHtml)

let testArr =dat.data.TeamRewardList
let testArrAll = []
for(let i = 0;i<testArr.length;i++){
if(testArr[i].AddTime){
testArrAll.push(testArr[i].AddTime)
}
}
for(let k=0;k<testArrAll.length;k++){
testArrAll[k] = new Date(testArrAll[k]).Format(‘MM-dd hh:mm’)
}
for(let j = 0;j<testArrAll.length;j++){
$(‘.timeArr’).html(testArrAll[j])
}

实现跳转功能
for(let i =0;i<aBtnAll.length;i++){
aBtnAll[i].addEventListener(‘tap’, function() {
mui.openWindow({
url: ‘machineDetail.html’,
// id: ‘MyrecordCenter’
});
});
}

.center {

left: 50%;

top: 50%;

transform: translate(-50%, -50%);

}

jq Tab
$(function(){
$(“.clickBtn div”).on(“click”,function(){
var index = $(this).index();
$(this).parents(“#box”).find(“.tabValueAll div”).eq(index).show().siblings().hide();
})
})

返回按钮功能实现
mui.init();
mui(“body”).on(“tap”, “.back”, function() {
backFn(window);
});

function backFn(w) {
var ws = null;
if(w.plus) {
console.log(1)
ws || (ws = plus.webview.currentWebview());
ws.close(‘auto’);
plus.webview.getWebviewById(‘BankCar’).reload();

    } else if(history.length > 1) {
        console.log(3)
        history.back();
    } else {
        w.close();
    }
}

验证码JS块
var countdown = 60;

function VerificationCodef() {
    var obj = $('.refresh');
    if(countdown == 60) {
        //                    
        mui.ajax({
            type: "get",
            url: apqurl + "/api/VerificationCode/"+phone,
            data: {

            },
            async: true,
            success: function(dat) {
                if(dat.success) {

// mui(“.collect”)[0].value = dat.data
mui.toast(dat.message);
} else {
mui.toast(dat.message);
}
}
});

        obj.attr("disabled", true);
        if(true) {
            countdown--;
        } else {
            obj.attr("disabled", false);
            obj.value = "获取验证码";
            countdown = 60;
            return;
        }
    }

    if(countdown == 0) {
        obj.attr("disabled", false);
        obj.innerHTML = "重新获取";
        countdown = 60;
        return;
    } else {
        obj.attr("disabled", true);
        countdown--;
        obj.text("重新发送" + countdown + "s");
    }
    setTimeout(function() {
        VerificationCodef()
    }, 1000)
}

$('.refresh').on('click', function() {
    VerificationCodef();
})

mui跳转页面的js块
$(“.adjunction”).click(function() {
mui.openWindow({
url: ‘addBank.html?type=0’,
id: ‘addBank’
});
});

获取用户信息
通过mui()的方式进行修改 不仅仅是innerText还有text $(“.exhibition_i”).text(val+”%”);
userInfo();

function userInfo() {
    mui.ajax({
        type: "get",
        url: apqurl + "/api/Mining/PersonalData?AccessToken=" + token,
        async: true,
        success: function(dat) {
            console.log(dat);
            if(dat.code == 200) {
                mui(".Tradable")[0].innerText = dat.data.DC_CanTradeCurrency;
                mui(".TFradable")[0].innerText = dat.data.CBDC_CanTradeCurrency;
            } else {

            }
        }
    });
}

mui框架的隐藏项
mui(“.projectile”)[0].classList.add(“mui-hidden”);

一般请求的方法
function issue(password) {
var Multiple = $(‘.currentPrice’).val();

    var purchase = $('.sale').val();
    var purchaseNum = $('.saleNum').val();

    ResetFunc();
    mui.ajax({
        type: "post",
        url: apqurl + '/api/Transaction/WhetherTheTransactionMatched',
        data: {
            AccessToken: token,
            'quantity': purchase,
            'price': purchaseNum,
            'type': 1,
            TransactionType: 3,
            AccessToken: token,
            password:password
        },
        async: true,
        success: function(dat) {
            if(dat.code == 200) {
                mui.toast(dat.message);
                JumpLi();
            } else {
                mui.toast(dat.message);
            }
        }
    })

};

复制粘贴
if(dat.success){
$(‘.walletAdder’).text(dat.data.WalletAddres)
$(‘#copty’).attr(‘data-clipboard-text’,dat.data.WalletAddres)

     let btn = document.getElementById('copty');
var clipboard = new Clipboard(btn);

clipboard.on('success', function (e) {
  console.log(e);
});

clipboard.on('error', function (e) {
  console.log(e);
});    
    }

vue组件封装

1

首先要把结构,方法 搭建好,

然后在子组件里面

父组件做的事情

  1. 设置一个方法,把变量值传给子组件
  2. 引入一个组件之后,要进行注入,compontens 还需要在template中写入标签
    1. 在这个标签里面
  1. 引入组件-3大步
1
2
3
4
5
6
7
8
9
10
import addDiagoPage from '@/components/addDiago.vue'

2. 组件注入
export default {
components: {
addDiagoPage
},

3. 组件标签
<addDiagoPage></addDiagoPage>
  1. 在组件标签里面进行参数的传递

    1
    2
    3
    4
    <!-- 添加用户标签 -->
    在子组件通过props进行接收
    <addDiagoPage :addFormVisible="addFormVisible" @close="closeState"></addDiagoPage>
    <!-- 这里是子组件告诉父组件,子组件触发了这个事件 @close--子组件触发this.$emit('close') --> 父组件就可以进行监听
  2. 父组件函数的书写

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    data(){
    return{
    addFormVisible: false,
    在第二步组件标签里面:addFormVisible="addFormVisible",就是把子组件里面的addFormVisible跟父组件的addFormVisible绑定在一起
    }
    }
    methods: {
    closeState () {
    this.addFormVisible = false
    }
    }
    监听子组件传来的事件: 也就是子组件发送this.$emit('close')的时候,实际上是触发父组件的closeState事件

子组件的内容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
<template>
<!-- 添加dialog -->
<el-dialog title="添加用户" :visible.sync="addFormVisible">
<el-form :model="addform" ref="addform" :rules="rules" label-width="100px" class="demo-ruleForm">
<el-form-item label="用户名" prop="username">
<el-input v-model="addform.username"></el-input>
</el-form-item>
<el-form-item label="密码" prop="password">
<el-input v-model="addform.password"></el-input>
</el-form-item>
<el-form-item label="邮箱" prop="email">
<el-input v-model="addform.email"></el-input>
</el-form-item>
<el-form-item label="电话" prop="mobile">
<el-input v-model="addform.mobile"></el-input>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click='closeSon'>关闭</el-button>
<el-button @click="addFormVisible = false">取 消</el-button>
<el-button type="primary" @click="addBtnUser">确 定</el-button>
</div>
</el-dialog>
<!-- 添加dialog结束 -->
</template>
<script>
import { addUser , roleList } from '@/api'
export default {
props: ['username', 'password', 'email', 'mobile', 'addFormVisible'],
data () {
return {
addform: {},
rules: {
username: [
{required: true, message: '请输入用户名', trigger: 'blur'}
],
password: [
{required: true, message: '请输入密码', trigger: 'blur'}
],
email: [
// 第一个规则是让用户一定要输入邮箱
{required: true, message: '请输入邮箱', trigger: 'blur'},
// 第二个校验规则是如果用户输入了内容,内容必须输入正确合法
// type: 'email':说明只能输入邮箱类型
{type: 'email', message: '请输入正确的邮箱地址', trigger: 'blur,change'}
],
mobile: [
{required: true, message: '请输入手机号', trigger: 'blur'}
]
}
}
},
methods: {
initFuction () {
roleList({params: {query: this.searchInfo, pagenum: this.pagenum, pagesize: this.pagesize}})
.then((res) => {
// console.log(res)
if (res.meta.status === 200) {
this.userList = res.data.users
this.total = res.data.total
}
})
},
// 添加的方法
closeSon () {
this.$emit('close')
},
addBtnUser () {
addUser(this.addform)
.then((res) => {
// console.log(res)
if (res.meta.status === 201) {
this.$message({
message: '添加角色成功',
type: 'success'
})
this.$emit('close')
this.initFuction()
} else {
this.$message({
message: '添加角色失败',
type: 'warning'
})
}
})
}
}
}
</script>

node的简单使用

首先先写一个服务器,采用express框架

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
/**
* Created by ken on 2018/7/26.
*/
// 引入模块
var express = require('express')
// 使用路由
var router = require('./router-express.js')
// 生成服务
var app = express()
// 监听接口
app.listen('3008',()=>{
console.log('http://127.0.0.1:3008')
})
/* app.on('request',(req,res)=>{

}) */
// 使用模板引擎:第一个参数是当前模板引擎所支持的文件类型
app.engine('html', require('express-art-template'));
app.set('view options', {
debug: process.env.NODE_ENV !== 'production'
});

app.use(express.static('public'))
app.use('/node_modules',express.static('node_modules'))

// 注入路由--使用当前路由的配置
app.use(router)

路由配置

1
2
3
4
5
6
7
8
9
10
11
12
13
var express = require('express')
引入自定义的处理函数
var handler = require("./handler-express")

// 通过Router函数创建路由模块对象
var router = express.Router()
// 设置-配置路由-告知router什么时候执行哪个函数
router.get('/data',handler.getDataInfo)
.get('/',handler.getIndex)


// 暴露路由
module.exports = router

路由配置处理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
引入数据库处理对象
var mymodule = require('./mymodule.-express.js')
暴露写法
exports.getDataInfo=(req,res)=>{
mymodule.getInfo((err,data)=>{
if(err){
res.end(err)
}else{
// 一定要注意,我们的数据操作模块中的返回的数据是数组,而不是对象
res.end(JSON.stringify(data))
// res.end(JSON.parse(data.toString()))
// console.log(data);
}
})
}

exports.getIndex=(req,res)=>{
mymodule.getIndex((err,data)=>{
if(err){
res.end('err')
}else{
// 一定要注意,我们的数据操作模块中的返回的数据是数组,而不是对象
// res.render(__dirname+"/views/index.html",data)
res.end(data)
}
})
}

数据库处理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
引入下载包
var mysql = require('mysql')
引入读取模块
var fs = require('fs')
配置数据库
var connection = mysql.createConnection({
host:'127.0.0.1',
user:'root', 连接sql名称
password:'123456',
database:'sanguo' 数据库名称
})
连接数据库
connection.connect()

暴露读取写法
module.exports.getInfo=(callback)=>{
// var sql = 'select * from index'
var sql = 'select name from zhuye' 选择zhuye这个设计表
// 执行Sql命令,并接收返回值
connection.query(sql,(err,result,fields) => {
console.log(result);
if(err){
callback(err)
}else{

callback(null,result)
}
})
}
这里module.exports 和exports是一样的
module.exports.getIndex=(callback)=>{
fs.readFile(__dirname+'/views/index.html',(err,data)=>{
/* console.log(err);
console.log('----------');
console.log(data); */
if(err){
callback(err)
}else{
callback(null,data.toString())
}
})
}

莫道征途路漫漫

扩展思维方式

小程序中使用textarea组件的使用,使用fixed=”true” 仍会出现滚动效果时,添加auto-height=”true” 在调试工具中会出现滚动,但在真机上就解决这个问题了

从这个实例,我发现不能以个人思维去看待文档,文档也会出错,要去实践才能得真知

小程序无法使用本地图片作为背景图

1
2
3
报错信息为:VM6971:2 pages/cashier/cashier.wxss 中的本地资源图片无法通过 WXSS 获取,可以使用网络图片,或者 base64,或者使用<image/>标签。请参考文档:    

我的解决方案是使用image读取本地图片,然后利用层级覆盖实现背景效果 , 因为我们所看到的平面,本质上是一个3D立体

小程序的checkbox样式问题

既然无法修改,就直接抛弃。自己写一个样式,点击更换,用data进行保存判断实现点击效果

数据无法更新到wxml的情况

使用 this.setData({

​ selectPic:wx.getStorageSync(“loginSel”)

​ })

异步数据无法快速同步到页面上,使用this.setData({})进行解决

还有一个是this.$apply() 是异步函数强制更新数据

#愿效滴水永不弃

flexible填坑

flexible是什么

淘宝手淘团队的移动适配方案

如何使用

引入

  1. 相对路径

    1. 1
      2
      <script src="build/flexible_css.debug.js"></script>
      <script src="build/flexible.debug.js"></script>
  2. cdn路径:

写入meta

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
if (!dpr && !scale) {
var isAndroid = win.navigator.appVersion.match(/android/gi);
var isIPhone = win.navigator.appVersion.match(/iphone/gi);
var devicePixelRatio = win.devicePixelRatio;
if (isIPhone) {
// iOS下,对于2和3的屏,用2倍的方案,其余的用1倍方案
if (devicePixelRatio >= 3 && (!dpr || dpr >= 3)) {
dpr = 3;
} else if (devicePixelRatio >= 2 && (!dpr || dpr >= 2)){
dpr = 2;
} else {
dpr = 1;
}
} else {
// 其他设备下,仍旧使用1倍的方案
dpr = 1;
}
scale = 1 / dpr;
}

上面的是灵活写法,也可以固定为普通屏

使用CSSREM配置px转换rem值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
1. 在vscode中安装完成之后修改默认配置
"cssrem.rootFontSize": 75 //设置默认字体大小
"cssrem.autoRemovePrefixZero":false //去除前缀为0

2. 在sublime中使用
下载本项目,比如:git clone https://github.com/flashlizi/cssrem
进入packages目录:Sublime Text -> Preferences -> Browse Packages...
复制下载的cssrem目录到刚才的packges目录里。
重启Sublime Text。
配置参数
参数配置文件:Sublime Text -> Preferences -> Package Settings -> cssrem

px_to_rem - px转rem的单位比例,默认为40。
max_rem_fraction_length - px转rem的小数部分的最大长度。默认为6。
available_file_types - 启用此插件的文件类型。默认为:[".css", ".less", ".sass"]。

最后是字体的书写

上面的都是样式布局的使用,但是我们要考虑的字体的显示

来自官方的语言:我们在iPhone3G和iPhone4的Retina屏下面,希望看到的文本字号是相同的。也就是说,我们**不希望文本在Retina屏幕下变小**,另外,我们**希望在大屏手机上看到更多文本**,以及,现在绝大多数的字体文件都自带一些点阵尺寸,通常是`16px`和`24px`,所以我们**不希望出现13px和15px这样的奇葩尺寸**。

如此一来,就决定了在制作H5的页面中,`rem`并不适合用到段落文本上。所以在Flexible整个适配方案中,考虑文本还是使用`px`作为单位。只不过使用`[data-dpr]`属性来区分不同`dpr`下的文本字号大小。

#### 所以我们应该这样做

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
定义一个scss函数   使用@mixin定义函数  使用@include来引用函数
@mixin font-dpr($font-size){
font-size: $font-size;

[data-dpr="2"] & {
font-size: $font-size * 2;
}

[data-dpr="3"] & {
font-size: $font-size * 3;
}
}
h3{
@include font-dpr(16px);
}

知识贵在实践~加油!

|