AVM(Application-View-Model)前端组件化开发模式基于标准Web Components组件化思想,提供包含虚拟DOM和Runtime的编程框架avm.js以及多端统一编译工具,完全兼容Web Components标准,同时兼容Vue和React语法糖编写代码,编译工具将Vue和React相关语法糖编译转换为avm.js代码。
基于标准 Web Components 组件化思想,兼容 Vue / React 语法特性,通过一次编码,分别编译为 App、小程序代码,实现多端开发。
组件功能介绍
该SKU组件可实现商品图片与颜色属性进行联动,通过颜色、版本来控制价格,总价通过购买数量与所选商品价格进行自动计算;可进行缺货设定。
编辑
上述功能点是通过商品数据结构和代码逻辑进行配合来实现的。
商品数据结构如下:
goodsList:[ {id:'100016015112', image:'https://m.360buyimg.com/mobilecms/s750x750_jfs/t1/210630/17/8651/208682/618a5bd6Eddc8ea0e/b5e55e1a03bc0126.jpg!q80.dpg.web', color:'亮黑色', status:true, guige:[ {label:'8G+128G',price:'3999',status:false}, {label:'8G+256G',price:'5999',status:true}, {label:'16G+512G',price:'6999',status:true}, {label:'16G+1024G',price:'9999',status:false} ]}, {id:'100016015113', image:'https://img14.360buyimg.com/n4/jfs/t1/216079/14/3895/201095/618a5c0cEe0b9e2ba/cf5b98fb6128a09e.jpg', color:'釉白色', status:true, guige:[ {label:'8G+128G',price:'3799',status:true}, {label:'8G+256G',price:'5799',status:true}, {label:'16G+512G',price:'6799',status:true}, {label:'16G+1024G',price:'9799',status:false} ]}, {id:'100016015132', image:'https://img14.360buyimg.com/n4/jfs/t1/215845/12/3788/221990/618a5c4dEc71cb4c7/7bd6eb8d17830991.jpg', color:'秘银色', status:true, guige:[ {label:'8G+128G',price:'3599',status:true}, {label:'8G+256G',price:'5599',status:true}, {label:'16G+512G',price:'6599',status:true}, {label:'16G+1024G',price:'9599',status:false} ]}, {id:'200016015117', image:'https://img14.360buyimg.com/n4/jfs/t1/203247/8/14659/237368/618a5c87Ecc968774/b0bb25331e5e2d1a.jpg', color:'夏日胡杨', status:false, guige:[ {label:'8G+128G',price:'3899',status:false}, {label:'8G+256G',price:'5899',status:false}, {label:'16G+512G',price:'6899',status:false}, {label:'16G+1024G',price:'9899',status:false} ]}, {id:'100013415456', image:'https://img14.360buyimg.com/n4/jfs/t1/160950/40/25098/234168/618a5cb9E65ba975e/7f8f93ea7767a51b.jpg', color:'冬日暖阳', status:true, guige:[ {label:'8G+128G',price:'3199',status:true}, {label:'8G+256G',price:'5199',status:true}, {label:'16G+512G',price:'6199',status:true}, {label:'16G+1024G',price:'9199',status:false} ]} ]
每个商品的版本有多条数据,每条数据都对应不同的价格,同时会有字段标识是否有货。
每一个商品也会有字段标识是否有货。
当切换商品属性时,需要通过函数进行判断,以保证在商品缺货的情况下,不能被选中。
setGoods(e){ // console.log(JSON.stringify(e)); let item = e.currentTarget.dataset.item; if(item.status){ this.data.selectGoods = item; this.data.guigeList = item.guige; for (let index = 0; index < item.guige.length; index++) { const element = item.guige[index]; //保证默认选中的商品是有货的 if(element.status){ this.data.selectGuige = element; break; } } } },
示例展示
编辑
组件开发
组件文件
easy-sku.stml
<template> <view class="easy-sku_container"> <view class="easy-sku_box"> <view class="easy-sku_base"> <view class="easy-sku_base-pic-box"> <image class="easy-sku_base-pic" src={selectGoods.image} mode="widthFix"></image> </view> <view class="easy-sku_base-info"> <text class="easy-sku_base-info-price">¥{selectGuige.price?selectGuige.price*count:0}</text> <text class="easy-sku_base-info-num">商品编号:{selectGoods.id}</text> </view> <view class="easy-sku_close-box" @click="cancel"> <image class="easy-sku_close-ico" src={ico_close} mode="widthFix"></image> </view> </view> <scroll-view class="easy-sku_scroll-box" scroll-y> <view class="easy-sku_guige-box"> <view class="easy-sku_guige-title"> <text class="easy-sku_guige-title-label">颜色</text> </view> <view class="easy-sku_guige-item-box"> <view :class="selectGoods.id==item.id?'easy-sku_guige-item--select':'easy-sku_guige-item--default'" v-for="(item,index) in goodsList" data-item={item} @click="setGoods"> <text :class="selectGoods.id==item.id?'easy-sku_guige-item-label-select':item.status?'easy-sku_guige-item-label--default':'easy-sku_guige-item-label-disable'">{item.color}</text> </view> </view> </view> <view class="easy-sku_guige-box"> <view class="easy-sku_guige-title"> <text class="easy-sku_guige-title-label">版本</text> </view> <view class="easy-sku_guige-item-box"> <view :class="selectGuige.label==item.label?'easy-sku_guige-item--select':'easy-sku_guige-item--default'" v-for="(item,index) in guigeList" data-item={item} @click="setGuige"> <text :class="selectGuige.label==item.label?'easy-sku_guige-item-label-select':item.status?'easy-sku_guige-item-label--default':'easy-sku_guige-item-label-disable'">{item.label}</text> </view> </view> </view> <view class="easy-sku_count-box"> <text class="easy-sku_count-label">购买数量</text> <view class="easy-sku_count-result-tool"> <text :class="count>0?'easy-sku_count-result-item':'easy-sku_count-result-item--disable'" @click="countDel">-</text> <input class="easy-sku_count-result-input" placeholder="" keyboard-type="number" v-model="count"/> <text class="easy-sku_count-result-item" @click="countAdd">+</text> </view> </view> </scroll-view> <view class="easy-sku_bottom"> <button class="easy-sku_btn" @click="submit">确认</button> </view> <safe-area></safe-area> </view> </view> </template> <script> export default { name: 'easy-sku', installed(){ this.data.selectGoods=this.props.goodsList[0]; // this.data.selectGuige=this.props.goodsList[0].guige[1]; this.data.guigeList = this.props.goodsList[0].guige; }, props:{ goodsList:Array, }, data() { return{ ico_close:'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAAjUlEQVR42mNgGNlg1qxZbTNnzrxFgvqnQJyLUwHQsKtA/B+InxEyDKjmI0gt0MD9hBQ+ImQozDAgvkyUV/AZSrJh+Awl2zBshlJsGBZDKTcMmjR+Ihn4kVqGHQS5jiJDkQ1D8j55hmIzjGxD8RlGsqFABe8IGYbF0Pv4FAUAXbiIhCS1ac6cOXYjvEwFAL7uy3s7L72GAAAAAElFTkSuQmCC', selectGoods:{}, selectGuige:{}, count:1, guigeList:[] } }, methods: { setGoods(e){ // console.log(JSON.stringify(e)); let item = e.currentTarget.dataset.item; if(item.status){ this.data.selectGoods = item; this.data.guigeList = item.guige; for (let index = 0; index < item.guige.length; index++) { const element = item.guige[index]; if(element.status){ this.data.selectGuige = element; break; } } } }, setGuige(e){ // console.log(JSON.stringify(e)); let item = e.currentTarget.dataset.item; if(item.status){ this.data.selectGuige = item; } }, countAdd(){ this.data.count++; }, countDel(){ if(this.data.count>0){ this.data.count--; } }, cancel(){ this.fire('cancel',''); }, submit(){ this.fire('submit',{goods:this.data.selectGoods,guige:this.data.selectGuige,count:this.data.count}); } } } </script> <style> .easy-sku_container { position: absolute; height: 100%; width: 100%; background-color: rgba(0,0,0,0.1); } .easy-sku_box{ align-items: center; justify-content: space-between; position: absolute; bottom: 0; width: 100%; height: 70%; background-color: #ffffff; border-top-left-radius: 30px; border-top-right-radius: 30px; padding: 15px; } .easy-sku_base{ width: 100%; padding: 15px; } .easy-sku_base-pic{ width: 80px; height: 80px; } .easy-sku_base{ flex-flow: row nowrap; justify-content: space-between; align-items: flex-end; } .easy-sku_base-info{ flex: 1; padding-left: 10px; } .easy-sku_base-info-price{ color: #fa2c19; font-size: 16px; } .easy-sku_base-info-num{ color: #666666; font-size: 12px; } .easy-sku_close-box{ height: 100%; } .easy-sku_close-ico{ width: 20px; } .easy-sku_scroll-box{ width: 100%; flex: 1; } .easy-sku_guige-box{ width: 100%; } .easy-sku_guige-title{ padding: 10px 0; } .easy-sku_guige-title-label{ font-size: 16px; font-weight: bolder; } .easy-sku_guige-item-box{ flex-flow: row wrap; justify-content: flex-start; align-items: center; } .easy-sku_guige-item--default{ background-color: #f2f2f2; border: 0.5px solid #f2f2f2; border-radius: 18px; padding: 8px 18px; margin-right: 10px; margin-bottom: 10px; } .easy-sku_guige-item-label--default{ font-size: 14px; color: #333333; } .easy-sku_guige-item--select{ background-color: #fee0dd; border: 0.5px solid #fa2c19; border-radius: 18px; padding: 8px 18px; margin-right: 10px; margin-bottom: 10px; } .easy-sku_guige-item-label-select{ font-size: 14px; color: #fa2c19; } .easy-sku_guige-item-label-disable{ font-size: 14px; color: #b5b5b5; /* text-decoration: line-through; */ } .easy-sku_count-box{ width: 100%; flex-flow: row nowrap; justify-content: space-between; align-items: center; margin-top: 10px; } .easy-sku_count-result-tool{ flex-flow: row nowrap; justify-content: space-between; align-items: center; } .easy-sku_count-result-item{ font-size: 25px; padding: 0 5px; color: #333333; } .easy-sku_count-result-item--disable{ font-size: 25px; padding: 0 5px; color: #b5b5b5; } .easy-sku_count-result-input{ background-color: #f0f0f0; border: 0; height: 18px; width: 40px; text-align: center; border-radius: 5px; } .easy-sku_count-label{ font-size: 16px; color: #333333; } .easy-sku_bottom{ width: 100%; } .easy-sku_btn{ background-color: #fa2c19; border-radius: 21px; font-size: 15px; color: #fff; padding: 10px; } </style>
组件使用说明
本组件是基于AVM.js开发的多端组件,通常同时适配Android、iOS、小程序、H5 , 具体支持情况还要看每个组件的说明文档。
首先需要登录开发平台,http://www.apicloud.com。 通过控制平台右上方的模块Store进入,然后选择AVM组件。
编辑
编辑
找到对应模块进入,也可通过搜索栏,通过组件名称关键字进行检索。
编辑
进入模块详情,点击立即下载下载完整的组件安装包。
编辑
组件压缩包的文件目录如下
编辑
也可通过查看模块文档 来了解模块的具体参数,引用的原生模块,注意事项等。
编辑 具体在项目中的使用步骤是,第一步将压缩文件中的easy-sku.stml文件拷贝到项目的components目录,通过阅读readme.md 文档和查看demo示例文件 demo-easy-sku.stml在需要开发的stml文件中,引入组件文件,完成页面的开发。
demo-easy-sku.stml
<template> <view class="page"> <safe-area></safe-area> <view class="item" @click="openSKU"> <text>选择商品</text> </view> <easy-sku oncancel="closeSKU" onsubmit="getSKU" :goodsList="goodsList" v-if="isShow" > </easy-sku> </view> </template> <script> import '../../components/easy-sku.stml' export default { name: 'demo-easy-sku', apiready(){//like created }, data() { return{ isShow:false, goodsList:[ {id:'100016015112', image:'https://m.360buyimg.com/mobilecms/s750x750_jfs/t1/210630/17/8651/208682/618a5bd6Eddc8ea0e/b5e55e1a03bc0126.jpg!q80.dpg.web', color:'亮黑色', status:true, guige:[ {label:'8G+128G',price:'3999',status:false}, {label:'8G+256G',price:'5999',status:true}, {label:'16G+512G',price:'6999',status:true}, {label:'16G+1024G',price:'9999',status:false} ]}, {id:'100016015113', image:'https://img14.360buyimg.com/n4/jfs/t1/216079/14/3895/201095/618a5c0cEe0b9e2ba/cf5b98fb6128a09e.jpg', color:'釉白色', status:true, guige:[ {label:'8G+128G',price:'3799',status:true}, {label:'8G+256G',price:'5799',status:true}, {label:'16G+512G',price:'6799',status:true}, {label:'16G+1024G',price:'9799',status:false} ]}, {id:'100016015132', image:'https://img14.360buyimg.com/n4/jfs/t1/215845/12/3788/221990/618a5c4dEc71cb4c7/7bd6eb8d17830991.jpg', color:'秘银色', status:true,guige:[ {label:'8G+128G',price:'3599',status:true}, {label:'8G+256G',price:'5599',status:true}, {label:'16G+512G',price:'6599',status:true}, {label:'16G+1024G',price:'9599',status:false} ]}, {id:'200016015117', image:'https://img14.360buyimg.com/n4/jfs/t1/203247/8/14659/237368/618a5c87Ecc968774/b0bb25331e5e2d1a.jpg', color:'夏日胡杨',status:false, guige:[ {label:'8G+128G',price:'3899',status:false}, {label:'8G+256G',price:'5899',status:false}, {label:'16G+512G',price:'6899',status:false}, {label:'16G+1024G',price:'9899',status:false} ]}, {id:'100013415456', image:'https://img14.360buyimg.com/n4/jfs/t1/160950/40/25098/234168/618a5cb9E65ba975e/7f8f93ea7767a51b.jpg', color:'冬日暖阳', status:true,guige:[ {label:'8G+128G',price:'3199',status:true}, {label:'8G+256G',price:'5199',status:true}, {label:'16G+512G',price:'6199',status:true}, {label:'16G+1024G',price:'9199',status:false} ]} ], } }, methods: { openSKU(){ this.data.isShow=true; }, closeSKU(){ this.data.isShow=false; }, getSKU(e){ console.log(JSON.stringify(e)); api.toast({ msg:'颜色:'+e.detail.goods.color+'/规格:'+e.detail.guige.label+'/数量:'+e.detail.count+'/总价:'+e.detail.count*e.detail.guige.price, location:'middle' }) this.data.isShow = false; } } } </script> <style> .page { height: 100%; background-color: #f6f6f6; } .item{ background-color: #ffffff; margin: 15px; padding: 15px; border-radius: 5px; } </style>
如果在AVM组件库中,没有找到实际项目中需要的组件,可以自己尝试封装组件。
编辑