合规国际互联网加速 OSASE为企业客户提供高速稳定SD-WAN国际加速解决方案。 广告
[TOC] # 实战:加载贝店商品列表 工程文件:UniAPP Basic # 工具准备 > 要实现跨域请求,在HTML5中需要安装Chrome插件“Allow CORS: Access-Control-Allow-Origin” 通过QQ浏览器插件搜索cors,安装以下插件: ![](https://box.kancloud.cn/d0c98408adf9787ba942424ed951bee1_988x320.png) > Easily add (Access-Control-Allow-Origin: \*) rule to the response header. > 安装完后要在工具栏启用该插件 Allow CORS: Access-Control-Allow-Origin lets you easily perform cross-domain Ajax requests in web applications. Simply activate the add-on and perform the request. CORS or Cross Origin Resource Sharing is blocked in modern browsers by default (in JavaScript APIs). Installing this add-on will allow you to unblock this feature. Please note that, when the add-on is added to your browser, it is in-active by default (toolbar icon is grey C letter). If you want to activate the add-on, please press on the toolbar icon once. The icon will turn to orange C letter. If you have a feature request, or found a bug to report, please fill the bug report form in the add-on's homepage ([http://mybrowseraddon.com/access-control-allow-origin.html](http://mybrowseraddon.com/access-control-allow-origin.html)). > 直接从官方网站下载安装,需要你能够访问Google网站 # 项目分析 贝店是一个社区营销模式的新型的电商平台,允许个人开设贝店,例如作者的贝店邀请码为690638,任何人下载贝店APP,输入邀请码就可以使用贝店购物,同时也可以申请自行开店,每一个贝店有一个唯一的编号,比如作者的贝店编号(shop\_id)为682731用于识别分享的商品的来源,点击以下链接可以直达我的贝店: ``` https://m.beidian.com/shop/shopkeeper.html?shop_id=682731 ``` 以下的示例从贝店加载推荐产品列表。贝店提供推荐列表的API格式如下: ``` https://api.beidian.com/mroute.html?method=beidian.h5.shop.product.list&page=1&shop_id=682731 ``` 其中有两个参数:加载的数据分页page和贝店的编号shop\_id,返回JSON格式的数据,包含几个域,如图所示 ![](https://box.kancloud.cn/db04fca0ee4300a9124f1b14addce89d_206x223.png) 这里我们只用到shop\_products字段,该字段包含贝店店主推荐的商品列表,商品的价格以分为单位,shop\_products的格式如下 ![](https://box.kancloud.cn/cc7acbe5d65bbabbdbb766d0d93cb14d_849x261.png) 商品详情页面的链接格式为: ``` https://m.beidian.com/detail/detail.html?iid=29064225&shop_id=682731 ``` 其中iid为产品的主键,贝店产品详情页面信息在WebView中无法打开,需要使用外部浏览器浏览。 # 迭代1 > 可能会因为商品已经下架导致不能浏览,请更换一个商品ID测试就可以了。 定义模版 ![](https://box.kancloud.cn/0f3814251db444383334aa1b55724ac9_1023x800.png) 根据需求设计如图所示模版,这里为了方便观察,给每一个视图显示了边框。 ![](https://box.kancloud.cn/edc906a205cbc477a683524b381ab0dc_1023x800.png) 本项目使用原生的Flex布局。布局阶段图片使用占位图图片生成工具`https://placeholder.com/`,参数为图片的宽度x高度,单位为像素。 [http://via.placeholder.com/750x250](http://via.placeholder.com/750x250) ``` <template> <view style="flex-direction: column; flex: 1;"> <view class=""> <view style="flex-direction: column; flex: 1;"> <view style="height: 750upx;"> <image src="http://via.placeholder.com/750x750" mode="" style="width: 100%; height: 100%;"></image> </view> <view style="padding-top: 30upx; padding-left: 20upx; padding-right: 20upx; font-size: 30upx; font-weight: bold;"> 启蒙积木小汽车小飞机组合套装儿童益智拼装积木玩具10小盒展示礼盒装</view> <view style="padding: 20upx;"> <view> <view> ¥100 </view> <view style="padding-left: 20upx;"> 2.13万人在买 </view> </view> <view style="flex: 1; justify-content: flex-end;"> <view> <button type="warn" size="mini">购买</button> </view> </view> </view> </view> </view> <view style="background-color: #8F8F94; height: 20upx;"></view> </view> </template> <script> var self; export default { data: {}, async onLoad() { self = this; } } </script> <style> view { /* margin: 10upx; border: #8F8F94 solid 1upx; */ display: flex; flex-direction: row; font-size: 28upx; } </style> ``` # 迭代2 填充数据 ``` <template> <view style="flex-direction: column; flex: 1;"> <block v-for="(item,index) in productList" :key="index"> <view class=""> <view style="flex-direction: column; flex: 1;"> <view style="height: 750upx;"> <image :src="item.img" mode="" style="width: 100%; height: 100%;"></image> </view> <view style="padding-top: 30upx; padding-left: 20upx; padding-right: 20upx; font-size: 30upx; font-weight: bold;"> {{item.title}}</view> <view style="padding: 20upx;"> <view> <view> ¥{{item.price}} </view> <view style="padding-left: 20upx;"> {{item.seller_count}} </view> </view> <view style="flex: 1; justify-content: flex-end;"> <view> <button type="warn" size="mini">购买</button> </view> </view> </view> </view> </view> <view style="background-color: #8F8F94; height: 20upx;"></view> </block> </view> </template> <script> var self; export default { data: { productList: [{ img: 'http://via.placeholder.com/750x750', title: '启蒙积木小汽车小飞机组合套装儿童益智拼装积木玩具10小盒展示礼盒装', price: '¥100', seller_count: '2.13万人在买' }, { img: 'http://via.placeholder.com/750x750', title: '启蒙积木小汽车小飞机组合套装儿童益智拼装积木玩具10小盒展示礼盒装', price: '¥100', seller_count: '2.13万人在买' }, ] }, async onLoad() { self = this; } } </script> <style> view { /* margin: 10upx; border: #8F8F94 solid 1upx; */ display: flex; flex-direction: row; font-size: 28upx; } </style> ``` # 迭代3 换成实际数据。 我们假设有更多的数据并尝试加载第一页数据,根据返回的字段has\_more判断是否还有更多的数据,如果有就更新页码再次加载数据,并将返回的数据合并到现有列表。这个例子我们只加载第一页数据。 ``` var self; export default { data: { productList: [] }, async onLoad() { self = this; let page = 1; let url = `https://api.beidian.com/mroute.html?method=beidian.h5.shop.product.list&page=${page}&shop_id=682731`; uni.request({ url: url, success(res) { const data = res.data; self.productList = data.shop_products; } }) } } ``` 在onLoad事件中,首先将实例指针保存到全局变量self方便在异步请求中访问实例本身。然后动态生成请求链接,使用uni.request异步请求服务器的数据,成功返回数据,将需要的shop\_products字段的内容保存到data的productList域,注意这里的this指针的作用域的更改。 ``` uni.request({ url: url, success(res) { const data = res.data; self.productList = data.shop_products; } }) ``` # 迭代4 接下来,我们希望在新的窗口打开商品的详情链接,详情页面的链接示例: ``` https://m.beidian.com/detail/detail.html?iid=29064225&shop_id=682731 ``` 由于在APP和微信小程序中打开外部链接的权限不一样,所以使用条件编译分别处理对应的逻辑。贝店网页版代码限制WebView模式下无法打开详情页,因此调用外部浏览器打开。 > 条件编译请阅读官方的文档 [https://uniapp.dcloud.io/platform](https://uniapp.dcloud.io/platform) ``` // 贝店程序限制,WebView模式下无法打开详情页,调用外部浏览器打开 // #ifdef APP-PLUS plus.runtime.openURL(api) // #endif 在微信小程序中无法直接打开外部链接,因此我们将链接复制到剪贴板,提示用户在浏览器中打开。 // #ifdef MP-WEIXIN uni.setClipboardData({ data: api, success: function () { uni.showModal({ title: '提示', content: '链接已复制,请在浏览器中访问', showCancel: false, }); } }) // #endif ``` 完整的事件处理代码: ``` methods: { buy(e) { //获取自定义属性的值 const item = e.target.dataset.item; console.log(item) //https://m.beidian.com/detail/detail.html?iid=29064225&shop_id=682731 let iid = item.iid; let api = `https://m.beidian.com/detail/detail.html?iid=${iid}&shop_id=682731`; // 贝店程序限制,WebView模式下无法打开详情页,调用外部浏览器打开 // #ifdef APP-PLUS plus.runtime.openURL(api) // #endif // 微信小程序中暂时没有解决方案 // #ifdef MP-WEIXIN uni.setClipboardData({ data: api, success: function() { uni.showModal({ title: '提示', content: '链接已复制,请在浏览器中访问', showCancel: false, success: function(res) { if (res.confirm) { console.log('用户点击确定'); } else if (res.cancel) { console.log('用户点击取消'); } } }); } }) // #endif } } ``` 修改模版代码,增加购买按钮的事件处理 ``` <button type="warn" size="mini" :data-item="item" @tap="buy">购买</button> ``` ![](https://box.kancloud.cn/fe3e5b0602c93b376f5bb92f56a97fdb_1023x800.png)