# project **Repository Path**: xiao_kailang/project ## Basic Information - **Project Name**: project - **Description**: 小程序项目 - **Primary Language**: JavaScript - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 2 - **Forks**: 0 - **Created**: 2021-07-26 - **Last Updated**: 2021-11-18 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README ![1111.png](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/bcda6302886c46649ded78a81d846183~tplv-k3u1fbpfcp-watermark.image) # 仿王者荣耀小程序-攻略页面 ## 前言 "上号上号!!!你在干什么呢" 无论在何时何地身边总是会响起这熟悉的话语,这貌似在大学生生活中很普遍。 可惜可惜,本人什么游戏都玩,什么都不精,那我就必须在学习、工作方面努力了。 ![QQ图片20210818163048.jpg](https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/46686862797646f7b1feabf62879d9b5~tplv-k3u1fbpfcp-watermark.image) 作为一名在校生,小程序是一种对全栈项目最好的练习,也是一个必备的知识点。正好王者荣耀小程序是一个不错的小程序,其中也有一个攻略页面。 开冲! ![16C343A9.png](https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/93b0f098de0b4ee2809eda393161592a~tplv-k3u1fbpfcp-watermark.image) - 更新记录 2021/8/22更新新闻点赞效果 ## IDE - [微信开发者工具](https://developers.weixin.qq.com/miniprogram/dev/devtools/download.html?t=201822) - [Fiddler](https://www.telerik.com/download/fiddler) 抓包软件,可以抓取小程序里的图片 - [Mark Man](http://www.getmarkman.com/) 测量设计图片内响应的样式 ## 总体架构 - 该项目是微信小程序云开发项目,使用wxml+wxss+js+component+云数据库结合,命名格式采用[BEM](https://blog.csdn.net/weixin_59695963/article/details/118586222)格式。 ```js |-wzry 项目名 |-cloudfunctions 云函数模块 |-miniprogram 项目模块 |-components 自定义组件 |-herosType 英雄信息排列组件 |-navBarTitle 自定义topbar组件 |-newsPoster 新闻文章组件 |-data 自定义数据 |-allHeros.js 封装获取云数据 |-acticleData.js 用户文章数据 |-circleList.js 新闻文章数据和新闻类型列表 |-herosMap.js 英雄图鉴中最新英雄 |-herosRank.js 3个上分英雄 |-segment.js 段位排行 |-upScoreData.js 上分页面数据 |-miniprogram_npm 构建有赞组件库 |-pages 页面 |-introduction 攻略主页面 |-upScore 上分宝典页面 |-heros 全部英雄页面 |-search 搜索页面 |-style 样式库 weui.wxss weui样式库 app.js 全局js app.json 全局json配置 app.wxss 全局wxss ``` 其中的data文件下全为固定数据,采用`module.exports`暴露,在需要使用的地方,可以使用`const {getHeroOrderByType} = require("../../data/allHeros")`进行引入,这里`{}`使用的是es6 的`解构`,当然也可以直接用一个常量接受使用。 关于云数据库,我采用的是`csv`格式进行`导入小程序云数据库表`中,`csv`格式制作,可以先创建一个`excel文件`进行编辑数据,然后`另存为csv格式`,需要注意的一点,文件中的中文需要转换为`utf-8编码`,可以在另存为csv格式前,先修改文件格式为txt,然后通过vscode进行修改编码格式,接着在改回excel格式,最后另存为csv格式。 ![image.png](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/12fcbbaf1ca84b59ab4fe7326b9ef8a2~tplv-k3u1fbpfcp-watermark.image) ## 项目规划 将项目的架构搭建后,分析各页面的功能,思考相互页面之间的联系,清楚如何进行动态数据绑定,如何获取数据,各页面有哪些细节需要注意等等。 ## 项目解构 以下就是我的所有页面 |![image.png](https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/bd597c91062c4fa59da625842f50d08b~tplv-k3u1fbpfcp-watermark.image) | ![image.png](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/4585e6e5ab4e46c0a7893e4af917d9fd~tplv-k3u1fbpfcp-watermark.image)| | --- | --- | |![image.png](https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/ba67b5bc445744da9a8d7d5420c63a3f~tplv-k3u1fbpfcp-watermark.image)|![image.png](https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/76502a65fd3e4ddb8255097a56f354ef~tplv-k3u1fbpfcp-watermark.image)| | ![image.png](https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/7ceafd0775e9480db2e85eae85ec494c~tplv-k3u1fbpfcp-watermark.image) | ![image.png](https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/7276fe41c2434365b8fe0092eb76e2e9~tplv-k3u1fbpfcp-watermark.image) | | ![image.png](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/9d71daffcbc649d8a8cd27399936b1db~tplv-k3u1fbpfcp-watermark.image)| ### tabbar 由于微信自带的tabbar格式就可以满足王者荣耀小程序的tabbar就没有再去自定义tabbar,而是直接使用默认格式了。写在`app.json`中,pagePath只有一个页面,其他页面由团队其他人负责,我这就没有修改成他们的。 ```js "tabBar": { "selectedColor": "#a68f5c", "borderStyle": "white", "backgroundColor": "#fff", "list": [ { "text": "主页", "iconPath": "images/tabbar/home.png", "pagePath": "pages/Introduction/Introduction", "selectedIconPath": "images/tabbar/home_on.png" }, { "text": "精选", "iconPath": "images/tabbar/jingxuan.png", "pagePath": "pages/Introduction/Introduction", "selectedIconPath": "images/tabbar/jingxuan_on.png" }, { "text": "攻略", "iconPath": "images/tabbar/hero.png", "pagePath": "pages/Introduction/Introduction", "selectedIconPath": "images/tabbar/hero_on.png" }, { "text": "我", "iconPath": "images/tabbar/wo.png", "pagePath": "pages/Introduction/Introduction", "selectedIconPath": "images/tabbar/wo_on.png" } ] }, ``` ### 精选主页 - **对页面分析** #### topbar 最上面的是topbar,王者荣耀小程序和默认的topbar格式不一样,所有我选择自定义组件, 这里取名字有点错误,当时以为topbar也属于navBar的一种。o(╥﹏╥)o ```js {{title}} ``` 这里让王者荣耀四个字和右边胶囊平齐没有使用类似`wx.setNavigationBarTitle`这样的接口,而是直接使用`css`中`padding-top`一点一点调。从父组件中传入两个参数,`isback`控制是否显示回退按钮(<),`title`为页面标题,`_goback`函数控制回到上一个页面,使用的是 `wx.navigateBack `API。 #### 中间部分 新英雄排列我做成了一个组件,因为在全部英雄中复用了两次。但组件是为全部英雄分类而做的,新英雄排列没有进行修改。 ```js {{type}} {{item.name}} ``` 其结构很简单,使用了弹性布局,开启了自动换行`flex-wrap: wrap;`,在css布局中对于各英雄之间的空白,我使用的是`margin-right`,但给第5个`.heros:nth-child(5)`设置为0。 上分排行榜: 给整个盒子绑定了一个点击事件`跳转到上分界面`,同样使用的是弹性布局,使用了3次弹性布局,整个大盒子是一个弹性盒,左边的文字也是一个,右边图片也是,图片右边的箭头是用伪类来做的,通过`transform: rotate(45deg);`旋转45度达到效果 ```js .heros-upImg::after{ content: ""; width: 16rpx; height: 16rpx; position: absolute; right: -16rpx; border-top:1px solid grey ; border-right:1px solid grey; transform: rotate(45deg); } ``` 点击全部英雄可以跳转到全部英雄界面 #### 用户文章和直播推荐 文章类型有三种情况,我都使用假数据完成了效果 1. 文章没有图片 2. 文章只有一张图片 3. 文章有3张及以上的图片 其中我将有图片和无图片分为两种情况书写(建议可以看看注释) ```js {{act.title}} {{act.content}} 共{{act.imgUrl.length}}张 {{item.id}}/{{nowArry.length}} ``` ![image.png](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/0e3e49789d33405c9c00fe193df6e4ba~tplv-k3u1fbpfcp-watermark.image) - 文字部分,使用了文字超出省略,如果是文字是单行省略,则可以使用`white-space: nowrap;overflow: hidden;text-overflow:ellipsis;`如果是固定行数省略,则可以使用 `overflow: hidden;display: -webkit-box;-webkit-line-clamp: 2; -webkit-box-orient: vertical;` ![image.png](https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/b30df35332aa43d1bfab9535e3efe701~tplv-k3u1fbpfcp-watermark.image) - 图片是排列用的是flex布局,为了获取到图片中件部分,在这里还使用了定位,`left: 50%;top:50%;transform: translate(-50%,-50%);`做到绝对居中。 ![遮罩层演示.gif](https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/dfa1694454ed4776b21bfdcb860eb261~tplv-k3u1fbpfcp-watermark.image) - 有图片的文章设置了有赞组件[遮罩层](https://vant-contrib.gitee.io/vant-weapp/#/overlay),通过点击事件修改`show`数据为`true`将图片放大,在组件基础上添加可以进行滑动图片,缺点是没发将右上角胶囊覆盖住。 - 遮罩层如何完成交互的呢~~~ 我给每张图片的父容器绑定了一个捕获事件(防止冒泡)`onClickShow`,然后使用`data-id="{{act.id},data-index="{{item.id}}`将数据中每篇文章的唯一标识`id`和每个图片的唯一标识`id`传入函数中(id为文章标识,index为图片标识),可以通过函数的默认参数`event`,打印event参数可以得到下图。传过来的id放在`event.currentTarget.dataset`中,显示图片和滑动图片并不难,但要保证所选的文章和图片要保持一致,(如最上方的数字)这是就需要用到传入的数据,通过`this.setData`方法将`index-1`作为`swiper`的`current`属性、`id-1`作为文章数组的下标。(这里减一的原因是我数据中都是从1开始的)。 ![image.png](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/02bc840a509f4e57bbb109c9ccdfd0e3~tplv-k3u1fbpfcp-watermark.image) ```js {{act.name}} {{act.desc}} ``` - 直播推荐:这里本来是点击跳转到另一个小程序的,但我不知道其他小程序的appid,所有就放弃了跳转而是使用了一个视频代替,使用了`video`标签 ### 上分宝典页面 值得一讲的地方就是这里也使用了[遮罩层](https://vant-contrib.gitee.io/vant-weapp/#/overlay),同样 这里还使用了[radio单选框组件](https://vant-contrib.gitee.io/vant-weapp/#/radio),对于交互功能,也通过引入`data中segment.js`段位数据,这里点击相应段位就会切换段位,通过对`radio`绑定点击事件传入`name`值修改data{}展示到页面的相关数据。 |![image.png](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/2cc772af8c3c466a9482c5ac27be7a90~tplv-k3u1fbpfcp-watermark.image)| |![image.png](https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/e18ec585b928430584e7618eae3a7f64~tplv-k3u1fbpfcp-watermark.image)| 最下面使用了一个小动画,使用方法为css动画`@keyframes`,修改定位中的`right`起到移动的效果,期间慢慢的修改`字体图标`的`opacity`透明度 ![箭头动画.gif](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/0ce7c5ff3ace4d4d93e31773bdcf309e~tplv-k3u1fbpfcp-watermark.image) #### 最强上分榜 最强上分榜、输出狂魔榜、开始上分都是上分宝典页面的一部分,写在siwper中的`swiper-item`。两个页面布局是一样的,写两个是为了展示展示。他们的布局很普通,使用了大量的弹性布局,然后在讲数据引入,使用它主要是因为好用,当然使用其他布局手段也可以。 ### 全部英雄 ![image.png](https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/a9268da057af497cb445acbdf46aec6a~tplv-k3u1fbpfcp-watermark.image) - 搜索框使用的是`weui`自带的搜索框,做了一点修改,点击搜索框会跳转到搜索页面进行搜索,减少全部英雄页面的负担。 - **该页面重点是下面的英雄分类,使用了云数据库。** 1. 建立好数据表 2. 引入数据表,进行筛选 3. 将筛选好的数据分类好分别插入wxml ![image.png](https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/c1ee818723a047c8b72955852e87133b~tplv-k3u1fbpfcp-watermark.image) - 建立数据表,我在开头已经写了方法,可以使用导入的方式,[英雄数据.csv](https://download.csdn.net/download/weixin_59695963/20933561),也可以自己一条一套记录添加 - 引入数据表,筛选分类,我将代码封装在`data文件`下的`allHeros.js`,注释很重要!!!! ```js //引入云数据库 const db = wx.cloud.database() const allHeros = db.collection("allHeros") // 将db.command设置为一个字符,方便使用 const _ = db.command // 设置每次获取数据记录的限制20条 const limit = 20 // 将获取数据封装为一个函数,然后只需要暴露函数就可 const getHeroOrderByType = async (type) => { // where 对云数据库进行筛选 let {data} = await allHeros.where(_.or([{ // _.or()或语句,不同字段不同值,符合一个就ok hero_type: _.eq(type) }, { hero_type2: _.eq(type) } ])).orderBy("hero_id", "desc").get() // orderBy() 排序,desc表示降序,asc表示升序 // 因为知道所有类型的数据都不超过40条 所以只要重复一次 // 如果超过40条,可以修改判断语句改为 while(data.length==limit*index) 需要定义一个变量index储存筛选次数 if(data.length ==20){ let arr = await allHeros.where(_.or([{ hero_type: _.eq(type) }, { hero_type2: _.eq(type) } ])).skip(limit).orderBy("hero_id", "desc").get(); data = [...data,...arr.data] // 将两次查询到的结果合并为一个数组 } //返回数组 return data } const allOccupation = { getHeroOrderByType } module.exports = allOccupation ``` - 在heros.js 引入封装好的筛选js,使用es7 的`async` 和`await` 来处理异步 ```js const {getHeroOrderByType} = require("../../data/allHeros") const type=["战士","法师","坦克","刺客","射手","辅助"] // 设置数据封装为函数 async getHeroType(){ this.setData({ zhanshi:await getHeroOrderByType(type[0]), fashi:await getHeroOrderByType(type[1]), tanke:await getHeroOrderByType(type[2]), cike:await getHeroOrderByType(type[3]), sheshou:await getHeroOrderByType(type[4]), fuzhu:await getHeroOrderByType(type[5]), }) }, onLoad(options) { this.getNewHeros() this.getHeroType() this.getnewsPost() }, ``` 赋值后的数组(zhanshi...)可以直接在wxml通过`wx:for="{{zhanshi}}"`使用 ### 新闻点赞 ![点赞.gif](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/c59e4a60797b440ea8b067bdcf09ce68~tplv-k3u1fbpfcp-watermark.image) 上图也使用了云数据库,点击修改云数据库中的support(点赞数)和supported(是否点赞过) - 上图使用`newsPoster组件`,交互功能:点击点赞数加1,颜色变红,在点减1,颜色恢复 将`更新数据代码`封装在`allHeros.js,`先在`父组件页面`引入allHeros.js`获取新闻数据`,然后传入`子组件`,通过`子组件`点击后将数据传入`父组件`,接着在父组件页面引入allHeros.js的`更新数据函数`:使用`where`筛选出需要修改的记录,然后使用`update`更新数据,在调用`更新数据函数`。 ```js //allHeros.js // 获取数据 const getNewsPost = async ()=>{ let {data} = await newsPost.orderBy("id","asc").get() return data } // 更新数据,修改点赞数 const updataNewsPost= async (id,support,supported)=>{ await newsPost.where({//根据自己设置的id筛选,也可以通过别的唯一字段筛选 id:_.eq(id) }).update({ data: { //需要修改的数据 support:support, supported:!supported } }) } // 子组件 methods: { onSupport(e){ let {support,id,supported}= e.currentTarget.dataset // 将数据传入父组件 this.triggerEvent("support",{support,id,supported}) } } // 父组件页面js引入 const {updataNewsPost} = require("../../data/allHeros") // 修改点赞数 async onSupport(e){ //获取数据 let {id,supported,support} = e.detail //判断是否点赞过 support在数据库中默认值为false if(!supported){ //点赞+1 await updataNewsPost(id,support+1,supported) }else{ //点击-1 await updataNewsPost(id,support-1,supported) } //重新让页面获取所有数据,达到渲染页面效果 this.getnewsPost() }, ``` ## 踩坑系列 ![image.png](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/0ad8711a665e4ec6bf453a5fb623c87b~tplv-k3u1fbpfcp-watermark.image) - 自定义topbar的时候回会导致整个页面会往上移动,需要设置topbar的高度,同样也要修改页面相关的高度。 - 遮罩层确定点击的当前文章以及滑动的图片,需要区分它们的唯一标识,this.setData要对应好数据。 - 只有一张图片的文章,当时用css搞了很久,一直都不对劲,一直查找资料,才发现修改image中mode属性就ok,心态直接起飞。 - 云数据库筛选的时候,let {data} 一定要加{},因为函数返回的是一个promise对象,对象之中才是我们想要的数组。 ## 个人体会 写完这些页面,个人感觉挺累的,虽然我负责的这些页面比较简单,交互功能较少,(云函数没用上o(╥﹏╥)o),第一次写小程序的精力,希望以后越来越好。 ![image.png](https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/68b3a50e6dec470f9f9c010062be30c7~tplv-k3u1fbpfcp-watermark.image) ## 源码 [源码](https://gitee.com/xiao_kailang/project) 欢迎大家给项目一个star, 鼓励开源更多的项目, 谢谢。