前言:这次的App项目是由native+H5组合而成,整个App分为2个模块,我负责的是商城首页到生成订单的一系列页面以及业务代码,在这里总结一下遇到的问题。第一次写笔记,多多见谅。
打包工具
项目采用webpack进行打包,虽然之前有过一些基础的接触,但是这次还是第一次自己尝试的去配置,稍微补了一下webpack的内容。
//webpack.config.js
module.exports = {
entry: {
ProductDetails:"./src/js/ProductDetails.js",
Orderdetail:"./src/js/Orderdetail.js",
Logistics:"./src/js/Logistics.js",
Index:"./src/js/Index.js",
...
},
output: {
path: './dist',
filename: '[name].js'
},
resolve: {
alias: {
'vue': 'vue/dist/vue.js',
}
},
module: {
loaders: [
{
test: /\.js$/,
loader: 'babel',
exclude: /node_modules/
},
{
test: /\.vue$/,
loader: 'vue'
},
{
test: /\.css$/,
loader: 'style-loader!css-loader!'
},
{
test: /\.scss$/,
exclude: /node_modules/,
loader: 'style-loader!css-loader!sass-loader'
},
{
test: /\.(png|jpg|gif|svg)$/,
loader: 'url'
}
]
},
}
入口
entry :配置起始文件的路径,它可以是数组,对象,字符串。在这里我采用了多页面入口的方式。
输出
output: path: 配置最终打包完成后的路径所在;filename:最终打包后文件的名称,由于是多页面入口文件,这里为了方便使用[name].js,这样最终打包出来的文件名称跟入口文件名称一致。
加载器
module(loaders):
test:注意是正则表达式,不要加引号,匹配要处理的文件
loader:要使用的loader,"-loader"可以省略
include: 把要处理的目录包括进来
exclude:不需要去处理的目录。
与native的交互
- 目前是通过自定义协议的方式,也就是URL,协商一个通用的协议比如app.owen://?pushcode=1 ,前端通过location.href,而native则是通过截取这段URL,获取里面的参数进行处理。
难点一.
模仿淘宝商品详情,虽然不要求完全一样但是功能基本要一致。难点就是在商品属性选择后价格,库存,图片都要改变,到这首先想到的就是Vue中的watch
.然后就是每种分类的点击效果,不冲突,不重复。
这里我想了很久该怎么做才能做到点击效果的同时又能使用
watch
监控,实现动态。经过不断的尝试我终于找到了方法,通过深入响应式原理了解,只有在data属性上的js对象都被会vue遍历再通过Object.definePropery
将全部属性转换getter/setter,可以通过console.log()
查看,它们在内部行了追踪依赖,才能实现响应。
在这里有个重点,Vue 不允许在已经创建的实例上动态添加新的根级响应式属性,也就是说我们只能动态添加在已存在的根级属性中,我在Vue创建了根级属性iscur
data: {
iscur: {},//当前的商品子属性attrid
}
可以通过this.$set(this.iscur,'b',2)
,但是如果新添加的新属性在改变后并不会触发更新怎么办,这里是采用this.someObject = Object.assign({}, this.someObject, { a: 1, b: 2 })
,创建一个新的对象,让它包含原对象的属性和新的属性。
言归正传,通过请求获取分类数据,这里我通过遍历父分类,给iscur动态添加属性,
this.arrts.forEach( (val, index)=> {
var attrsId = {
//设置子分类attrid
['type' + index]: ""
}
....
this.iscur = Object.assign({}, this.iscur, attrsId) //实现data响应
....
})
可以看到iscur 中的属性,
在看看HTML处:
//父分类
<div class="attr" v-for="(attr,findex) in arrts">
<h1 >{{attr.attrname}}</h1>
<ul :id="attr.attrid">
//子分类
<li v-for="(item,index) in attr.attrValueList"
:class="{active:iscur['type'+findex]==item.attrid}"
v-on:click="actives($event,findex,item.attrid)"
>{{item.attrname}}</li>
</ul>
</div>
首先分类信息会有两次遍历,首先遍历出父分类,再遍历子分类,其中:class="{active:iscur['type'+findex]==item.attrid}
是判断当前父分类下选中的是哪个子分类id。v-on:click="actives($event,findex,item.attrid)
点击子分类时将父分类的id和子分类的id传入
actives: function (e, findex, attrid) {
this.iscur['type' + findex] = attrid;
}
最后使用watch
监控iscur对象,在每次点击后,iscur就会发生改变,从而执行handler,
在其中执行对比sku,更换价格,图片,以及库存。
iscur: {
/*
监控 iscur 对象
当iscur中属性发生变化时,我们获取iscur中每个属性的value值,再与价格表中的数据进行对比,提取出相同项的数据
*/
handler: function (val) {
// do something
},
// 深度观察
deep: true
},
难点二.
这种类分页:
最开始做的时候也最简单,上面部分横向导航栏,下面展示商品,每次点击分类时候去请求相应的数据,替换掉展示商品部分的数据,这样的结果就是出现重复请求数据,体验也差。之后想试着优化这部分,看了主流app类似这种分类页效果,就是点击子分类,如果是第一次则加载数据,否则就显示数据,再次点击分类的时候刷新。
思路:首先我在data中设置一个属性
productlist
专门用来存放数据,默认值设置为一个空数组 ,在子分类成功后执行setModels
方法
setModels: function (datas) {
/**
* 初始化productlist的数据结构
* 根据分类数据遍历后分别添加obj,用来存放数据
*/
datas.forEach((value, index) => {
var obj = {
brandid: value.brandid,
list: []
}
this.productlist.push(obj)
})
},
通过这个方法,productlist
拥有了跟分类相同个数对象,之后每次点击子分类后去请求商品列表,然后遍历每个数据push到相应obj的list数组中,这样就保存了数据。当然点击时候还需要一个方法去判断什么时候去请求。
cacheData: function (index,brandid) {
/**
* 通过index知道分类的索引号,获取数据
* 如果list的长度为0,代表无数据,则去请求数据
*/
var indexdata=this.productlist[index]
if(indexdata.list.length==0){
this.getlistdata(brandid)
}else{
return false
}
},
Tips
this.$nextTick(function(){
//dom更新
})
这个方法通常是我们需要运用到dom时候调用的,比如swiper,js 在获取图片数据后,实例化swiper必须在该回调函数内执行才有效。获取一些其他第三方插件需要操作dom节点,获取边距等都需要在回调函数内执行。