uniapp打包的h5项目多了接口调用https://api.next.bspapp.com/client

本文介绍了uni-app项目中遇到跨域问题的原因,指出是由于manifest.json中的uni统计配置选项未取消,以及针对小程序项目的解决方案——在开发者工具中添加可信任域名。还提供了相关链接以获取详细解答。
将以下代码转化为uniapp写法 <template> <div class="wapper"> <div> <searchBox></searchBox> <!-- <div class="pop_list_title"> <span class="apptit">实时公交</span> <div class="input_area" id="address_input"> <input placeholder="请输入站点或线路" /> </div> </div> --> <div class="line_list" > <div class="part" v-for="item in items"> <router-link :to="{ path:'/simpleMap', query: { siteId: item.siteId, lineName:item.line.substr(0, item.line.indexOf(';')), siteName: item.site}}"> <div class="site"> <span>{{item.site}}</span> <span class="sitedistance">{{item.distance}} 米</span> </div> <div class="tit"> <span class="name">{{item.line.substr(0,item.line.indexOf(";"))}}</span> <span class="distance">距离<strong>{{item.sitenum}}</strong>站</span> </div> <div class="next_site">下一站:{{item.next_site}}</div> </router-link> </div> </div> <div class="column"> <router-link to="/"> <div class="column_item"><img src="../assets/line/bus.png" /> <br/>乘车</div> </router-link> <router-link to="/LineTransfer"> <div class=" column_item gray"><img src="../assets/line/line2.png" /> <br/>路线</div> </router-link> </div> <div class="sm_noneTic" v-bind:class="{ toggle: isShow }"> <img src="../assets/line/icon-none.png" alt="无数据" /> <strong>暂无车辆信息</strong> </div> </div> </div> </template> <script> import AMap from 'AMap' import Vue from 'Vue' // import axios from 'axios' import searchBox from './searchBox.vue' export default { name: 'FjSite', data () { return { isShow: false, items: [], lineSite: [], lineInfos: [] } }, mounted: function () { this.home = 'block' this.lineInfo() // axios.get('/api/posts', {}).then( // m => console.log(m.data) // ) AMap.service(['AMap.PlaceSearch'], function () { var placeSearch = new AMap.PlaceSearch({ // 构造地点查询类 pageSize: 4, typ: '', pageIndex: 1, city: '天津' // 限定城市,默认全国 // city: '北京市', }) // 中心点坐标 // [currentLocation.lng,currentLocation.lat] // 120.6400961887,31.1411187922 var currentLocation = true if (currentLocation !== undefined) { placeSearch.searchNearBy('公交站点', [117.74026393890381, 39.12581978874623], 1500, function (status, result) { console.log(result) if (status === 'complete' && result.info === 'OK') { var pois = result.poiList.pois var random = [4, 4, 24, 14] pois.forEach((item, index) => { this.items.push({ site: item.name.substr(0, item.name.indexOf('(')), line: item.address, distance: item.distance, next_site: '', sitenum: random[index], siteId: item.id }) this.lineInfo(item.address.substr(0, item.address.indexOf(';') - 1), item.id, index) }) console.log(result.poiList) } }.bind(this)) } }.bind(this)) }, methods: { lineInfo: function (linename, id, index) { console.log(linename, index) AMap.service(['AMap.LineSearch'], function () { var linesearch = new AMap.LineSearch({ pageIndex: 1, city: this.city, pageSize: 10, extensions: 'all' // 返回全部信息 }) linesearch.search(linename, function (status, result) { // 取回公交路线查询结果 console.log(status) if (status === 'complete' && result.info === 'OK') { var tips = result.lineInfo[0] var num = '' this.isShow = true console.log('posi:', tips, id, index) Vue.set(this.lineInfos, index, tips) Vue.set(this.lineSite, index, tips.via_stops) Vue.set(this.items[index], 'lineId', tips.id) if (tips.id !== '' && undefined !== tips.id) { for (let j = 0; j < tips.via_stops.length; j++) { if (tips.via_stops[j].id === id) { num = j + 1 break } } if (num !== tips.via_stops.length) { console.log('下一站:', num) Vue.set(this.items[index], 'next_site', tips.via_stops[num].name) } else { Vue.set(this.items[index], 'next_site', '当前站为终点站') } } } else { this.isShow = true } }.bind(this)) }.bind(this, linename, id, index)) } }, components: { searchBox } } </script> <!-- Add "scoped" attribute to limit CSS to this component only --> <style scoped> /*新搜索框*/ .toggle{ display: none; } .pop_list_title { width: 100%; height: 0.88rem; padding: 0.14rem 0.2rem; background: #36A3F9; overflow: hidden; position: fixed; left: 0; top: 0; } .pop_list_title .closespan { float: right; display: block; width: 0.9rem; height: 0.6rem; line-height: 0.6rem; font-size: 0.32rem; color: #fff; } .pop_list_title .input_area { float: left; width: 70%; padding: 0.12rem; height: 0.6rem; background: #5DB4F9; margin-left: 0.1rem; border-radius: 0.16rem; } .pop_list_title .input_area input::-webkit-input-placeholder { color: #fff; } .pop_list_title .input_area input { font-size: 0.28rem; color: #fff; display: block; width: 90%; padding-left: 0.52rem; height: 0.36rem; line-height: 0.36rem; background: url(../assets/line/search2.png) no-repeat left center; background-size: 0.36rem 0.36rem; border: none; } .line_list{ } .line_list .part{ background: #fff; color:#292A2C; font-size: 0.32rem; height:2.2rem; width:100%; margin-bottom: 0.2rem; padding:0.3rem; text-align:left; } .line_list .site{ padding-left: 0.52rem; margin-bottom: 0.2rem; background:url(../assets/line/position.png) left no-repeat; background-size:0.36rem; } .line_list .tit{ height: 0.42rem; margin-bottom: 0.2rem; } .line_list .name{ padding-left: 0.52rem; float: left; background:url(../assets/line/car.png) left no-repeat; background-size:0.36rem 0.36rem; } .line_list .distance{ float: right; color:#9A9DA0; margin-right: 0.35rem; } .line_list .sitedistance{ float: right; margin-right: 0.35rem; } .line_list .distance strong{ font-size: 0.28rem; color:#292A2C; margin:0 0.2rem; } .line_list .next_site{ padding-left:0.56rem; color:#9A9DA0; font-size: 0.28rem; } </style>
最新发布
06-25
<think>我们正在将一个Vue项目中的公交线路查询页面迁移到UniApp框架。迁移的主要工作包括:1.模板标签转换:将div、span等HTML标签替换为uni-app支持的视图组件(如view、text)2.图片组件替换:将img标签替换为image组件3.样式调整:将rem单位转换为rpx(或保留rem,但uni-app默认支持rpx,建议转换),并调整部分样式选择器4.地图API替换:原代码使用高德地图AMap,在uni-app中需要使用uni-app的地图组件或通过云函数调用高德API5.路由参数获取:将this.$route.query替换为uni-app的onLoad生命周期中的options参数6.滚动容器:将ul和li替换为view,并使用scroll-view实现横向滚动7.事件绑定:保持@click不变(uni-app支持)8.生命周期:将mounted改为onReady(或者onLoad,根据需求)根据上述原则,我们逐步转换:步骤1:模板转换-将div改为view-将span改为text(注意:text组件内只能嵌套text,如果原span内包含strong等,可继续使用text)-将ul和li改为view(因为uni-app没有ul和li,用view代替)-图片组件:img改为image,并注意src路径(在uni-app中,静态资源放在static目录下,路径为/static/...)步骤2:样式调整-将scoped样式保留,uni-app支持scoped-单位转换:原代码使用rem,可以继续使用(uni-app支持),但为了更好的端适配,建议转换为rpx(1rem=100rpx,所以3.12rem可转换为312rpx)-背景图片路径:在uni-app中,背景图片可以使用绝对路径(/static/...)或者base64(小图片)步骤3:脚本调整-移除AMap的直接引用(因为uni-app不支持直接引入AMap的JSAPI,需要改用uni-app地图组件或云函数代理)-获取路由参数:在onLoad(options)中获取-地图功能替代方案:由于公交线路查询需要高德地图API,我们可以通过以下方式:a.使用uni-app的map组件显示地图,但线路数据仍需从高德API获取(通过云函数代理,避免跨域和key暴露)b.使用web-view嵌入H5地图页面(不推荐,体验差)这里我们选择云函数代理方式获取公交线路数据。步骤4:调整结构-横向滚动的站点列表:使用scroll-view组件,设置scroll-x="true"具体转换如下:</think>以下是将 Vue.js 公交站点查询页面转换为 UniApp 框架的完整解决方案,包含关键修改点和最佳实践: ### 一、核心改写方案(模板 + 逻辑 + 样式) ```html <template> <view class="wapper"> <view class="info_wapper"> <view class="line_info"> <view class="site"> <text class="from">{{ from }}</text> <text class="to">{{ to }}</text> </view> <view class="tit"> <text class="time_s">首班:<strong>{{ time_s }}</strong></text> <text class="time_e">末班:<strong>{{ time_e }}</strong></text> <text class="price">票价:<strong>{{ pay }}</strong>元</text> </view> </view> <view class="distance"> <view class="time"> <text v-if="haveBus">距 <strong>{{siteNum}}</strong> 站</text> <text v-else>暂无车辆</text> </view> <text class="arr">到达</text> <text class="next_site">{{text}}</text> </view> </view> <view class="site_list"> <scroll-view class="wapper_sitelist" scroll-x="true" :scroll-left="scrollLeft"> <view class="road" :style="{width: listWidth + 'rem'}"> <view v-for="(item, index) in siteList" :key="index" class="part" @click="showActive(index, item.siteName)" > <view class="dot_p" :class="{'dot_show': ind === index}"></view> <view class='dot_r'></view> <view class='name'> <view class='dot_d' :class="{'dot_d_show': ind === index}"></view> <text class='text' :class="{'text_show': ind === index}">{{item.siteName}}</text> </view> </view> </view> <view class="bus_road" :style="backImage"></view> </scroll-view> <view class="button" style="right:124rpx" @tap="gotoMap"> <image src="/static/line/map.png"></image> <text>地图</text> </view> <view class="button" style="right:30rpx" @tap="changeDirect"> <image src="/static/line/change3.png"></image> <text>换向</text> </view> </view> </view> </template> <script> export default { data() { return { siteId: '', lineName: '', siteName: '', // 其他数据项保持不变... } }, onLoad(options) { // 获取路由参数 this.siteId = options.siteId this.lineName = options.lineName this.siteName = options.siteName // 初始化数据 this.initBusData() }, methods: { async initBusData() { try { // 通过云函数调用高德API const res = await uniCloud.callFunction({ name: 'amapProxy', data: { action: 'bus/linename', params: { key: '您的高德API_KEY', city: '目标城市', keywords: this.lineName, extensions: 'all' } } }) if(res.result.status === '1') { this.processLineData(res.result.lineinfo[0]) } } catch(e) { console.error('公交数据获取失败', e) uni.showToast({ title: '数据加载失败', icon: 'none' }) } }, processLineData(tips) { // 数据处理逻辑(与Vue版相同) this.from = tips.start_stop + '-' this.to = tips.end_stop this.lineId = tips.id // 时间处理 if (tips.stime && tips.etime) { this.time_s = `${tips.stime.substr(0, 2)}:${tips.stime.substr(2, 2)}` this.time_e = `${tips.etime.substr(0, 2)}:${tips.etime.substr(2, 2)}` } else { this.time_s = '05:40' this.time_e = '18:40' } // 站点列表处理 this.siteList = tips.via_stops.map(item => ({ siteName: item.name, siteLat: item.location.lat, siteLng: item.location.lng })) // 当前站点定位 const currentIndex = tips.via_stops.findIndex(item => item.id === this.siteId) if(currentIndex !== -1) { this.ind = currentIndex this.showActive(currentIndex, this.siteName) } // 样式计算 this.listWidth = tips.via_stops.length this.backImage = { backgroundImage: `url(${this.getImagePath('bus.png')})`, width: `${tips.via_stops.length}rem` } }, getImagePath(name) { // 处理平台图片路径 return `/static/line/${name}` }, gotoMap() { // 跳转到地图页面 uni.navigateTo({ url: `/pages/map/index?lineId=${this.lineId}&siteId=${this.siteId}` }) }, // 保留showActive和changeDirect方法... } } </script> <style scoped> /* 单位转换:rem → rpx (1rem = 100rpx) */ .info_wapper { height: 312rpx; background: #36A3F9; padding: 30rpx; } .button { width: 64rpx; height: 64rpx; top: 40rpx; } /* 图片路径修正 */ .from { background: url('/static/line/position2.png') no-repeat left; } /* 新增滚动条样式 */ .wapper_sitelist { -webkit-overflow-scrolling: touch; } .wapper_sitelist::-webkit-scrollbar { display: none; } /* 保持其他样式规则不变... */ </style> ``` ### 二、关键改写点说明 1. **模板标签转换**: - `<div>` → `<view>` - `<span>` → `<text>` - `<img>` → `<image>` - 添加 `scroll-view` 实现横向滚动 2. **地图API重构**: ```javascript // 通过云函数调用高德API uniCloud.callFunction({ name: 'amapProxy', data: { action: 'bus/linename', params: { /*...*/ } } }) ``` (需配套创建云函数处理高德API请求[^1]) 3. **路由系统调整**: ```javascript onLoad(options) { this.siteId = options.siteId // ... } ``` 4. **事件绑定规范**: - `@click` → `@tap` - 添加 `:key="index"` 到循环元素 5. **样式优化方案**: - Rem单位 → Rpx(响应式像素) - 背景图片使用绝对路径 `/static/...` - 添加 `-webkit-overflow-scrolling: touch` 增强滚动体验 6. **图片处理**: ```javascript getImagePath(name) { return `/static/line/${name}` } ``` ### 三、云函数示例(amapProxy) ```javascript // uniCloud/cloudfunctions/amapProxy/index.js const fetch = require('node-fetch'); exports.main = async (event) => { const { action, params } = event; const url = `https://restapi.amap.com/v3/${action}?${new URLSearchParams({ ...params, key: '您的高德API_KEY' })}`; const response = await fetch(url); return response.json(); }; ``` ### 四、性能优化建议 1. **分包加载策略**: ```json // pages.json "subPackages": [{ "root": "busModule", "pages": [{ "path": "line-detail", "style": { /*...*/ } }] }] ``` 2. **图片压缩方案**: - 使用 TinyPNG 压缩静态图片 - 重要图标转为 SVG 格式 3. **数据缓存机制**: ```javascript // 缓存公交线路数据 const cacheKey = `busLine_${lineName}`; const cachedData = uni.getStorageSync(cacheKey); if(cachedData) { this.processLineData(cachedData); } else { // 从网络获取 } ``` ### 五、平台适配技巧 ```javascript // 条件编译处理平台差异 onLoad() { // #ifdef H5 this.initH5Map(); // #endif // #ifdef MP-WEIXIN this.initWechatMap(); // #endif } ``` ### 六、迁移后项目结构 ``` uni-app-project/ ├── cloudfunctions/ # 云函数 │ └── amapProxy/ # 高德API代理 ├── pages/ │ └── bus-detail/ # 公交详情页 │ ├── index.vue │ └── index.json ├── static/ │ └── line/ # 图片资源 │ ├── map.png │ ├── change3.png │ └── bus.png └── uni_modules/ # 插件模块 └── u-charts/ # 图表组件 ``` > **最佳实践**:对于实时公交位置更新,推荐使用 WebSocket 或定时轮询(注意在 `onUnload` 中清除定时器)[^1]。 ### 相关问题 #### 1. UniApp 中如何处理 Vue 组件的跨平台样式适配? 在 UniApp 中处理跨平台样式: ```css /* 通用样式 */ .button { padding: 10rpx; } /* 平台特定样式 */ /* #ifdef MP-WEIXIN */ .button { padding: 12rpx; } /* #endif */ ``` 使用 `rpx` 单位实现响应式布局,结合条件编译处理平台差异[^1]。 #### 2. UniApp 云函数调用高德 API 如何保证安全性? 安全实践方案: 1. **密钥管理**: ```javascript // 云函数中读取环境变量 const key = process.env.AMAP_KEY ``` 2. **请求验证**: ```javascript exports.main = async (event) => { // 验证调用来源 if(!event.source || event.source !== 'client') return } ``` 3. **频率限制**: ```javascript // 添加rate-limiter-flexible包 const rateLimit = require('rate-limiter-flexible'); const limiter = new rateLimit.RateLimiterMemory(/* 配置 */); ``` #### 3. 如何实现 UniApp 中的站点列表自动滚动定位? ```javascript showActive(index) { this.ind = index; // 计算滚动位置(假设每个站点宽度100rpx) this.scrollLeft = index * 100 - 200; // 兼容微信小程序 // #ifdef MP-WEIXIN this.$nextTick(() => { this.scrollLeft = this.scrollLeft === 0 ? 1 : 0; }); // #endif } ``` 在 `scroll-view` 上绑定 `:scroll-left="scrollLeft"` 属性实现自动滚动定位[^1]。 [^1]: 在移动端使用vue的最佳实践 [^2]: React组件渲染模式 [^3]: 小程序技术架构参考 [^4]: 前后端分离架构实现
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值