专栏首页HLQ_Struggle微信小程序 Notes|开发常用事例(三)

微信小程序 Notes|开发常用事例(三)

前言

之前涉足小程序,简短的记录了下开发过程中遇到的点点滴滴。

而今再次负责小程序,时隔许久,真是一片懵逼,多亏了之前的简短记录,这里将会不断记录完善开发过程中遇到的一系列的小问题。

总是要不断努力,买车到现在,各种无奈,似乎国庆回来整个人都不好了,得赶紧调整了,不然梦想始终只是梦想了。

加油~

小事例汇总

对于不熟悉前端的 Android 而言,前端是真的烦,说不清因为哪儿个属性就冲突了。相对比较好的一点是在线调试,调整参数样式,直接拷贝。什么时候 Android 也能有这样的神器就好了,哇咔咔,期待我 Android 越来越好~

1. 微信小程序如何构建 npm?

之前一直都是 Android 为主,突然在某个官网看到需要通过 npm 方式构建,顿时有点懵逼,这里记录下步骤,方便下次直接分分钟搞定~

Step 1:进入小程序根目录执行 npm 初始化

  • npm init

成功后会生成 package.json 文件。

Step 2:随后执行对应的 npm 安装依赖

例如这里需要使用有赞组件库 vant,所以对应的 npm 命令如下:

  • npm i @vant/weapp -S --production

这两步对应的示意图如下:

Step 3:在小程序开发工具中选择构建 npm。

这里需要注意一定在项目本地设置中打开 npm:

成功后会生成 miniprogram_npm 目录,里面变包含我们通过 npm 下载的 vant 代码了,如下:

2. 如何升级 npm 对应依赖包?

某天逛官网时挺懵逼的,看到人版本都提升几个了,无从下手,这里放上升级方式,其实和之前一毛一样,如下升级 vant 事例图:

其实还是把官网提供的 npm 安装方式拷贝运行一次。

3. 如何点击 image 进入客服会话?

先附上效果图:

由于微信小程序 Api 中注明只有 button 才具有一些开放功能,而单独的 image 则无法实现点击跳转客服消息会话功能。前端个人感觉就是一个个元素通过不同的属性样式包罗万象,那么我能不能通过 button 包裹 image 间接实现这个效果呢?一起来看~

<view class="model">
  <button open-type="contact">
    <image mode="aspectFit" src="/images/img_07.png" />
  </button>
  <!-- ... -->
</view>

样式文件如下:

.model {
  display: flex;
  justify-content: space-between;
  margin-top: 30rpx;
}

.model button {
  height: 180rpx;
  width: 49%;
  background-color: transparent !important;
  margin: 0;
  padding: 0 !important;
}

.model button::after {
  border: 0px solid rgba(0, 0, 0, 0.2) !important;
}

.content .model button image {
  width: 100%;
}

4. 如何打开/预览云平台 PDF?

先来看下粗略的效果图:

大概是有那么点意思:

  • 支持打开/预览在线 PDF;
  • 支持显示 PDF 原有名称;
  • 支持分享、收藏。

其实还是下载本地,然后打开,高大上忽悠就是支持预览在线 PDF,?

先来看下我本地模拟的基础数据:

newsList: [{
        newID: 0,
        title: '最新活动',
        content: '游艇xx活动',
        pdfUrl: urlUtils.getDownloadPDFUrl('/pdf/xxn.pdf'),
        createTime: '2020 年 4 月 1 日'
      },
      {
        newID: 1,
        title: '产业政策',
        content: '海南省xxx通知',
        pdfUrl: urlUtils.getDownloadPDFUrl('/pdf/xx.pdf'),
        createTime: '2019 年 12 月 30 日'
      },
      {
        newID: 2,
        title: '最新内容',
        content: '游艇xx名单',
        pdfUrl: urlUtils.getDownloadPDFUrl('/pdf/xx.pdf'),
        createTime: '2020 年 4 月 1 日'
      }
    ],

随后附上关键代码:

/**
 * 加载 PDF 文档
 */
onLoadItemPDF: function(event) {
  wx.showLoading({
    title: '文件缓冲中...',
  })
  var itemId = parseInt(event.currentTarget.dataset.newsid);
  var saveTempFilePath = wx.env.USER_DATA_PATH + '/temp.pdf';
  var newFilePath = wx.env.USER_DATA_PATH + '/' + this.data.newsList[itemId].content + '.pdf';
  wx.downloadFile({
    url: this.data.newsList[itemId].pdfUrl,
    filePath: saveTempFilePath,
    success: function(res) {
      if (res.statusCode == 200) {
        var fileSystemManager = wx.getFileSystemManager();
        fileSystemManager.rename({
          oldPath: saveTempFilePath,
          newPath: newFilePath,
          success: function(res) {
            wx.openDocument({
              filePath: newFilePath,
              fileType: 'pdf',
              showMenu: 'true',
              success: function(res) {
                console.log("----> 打开文档成功 ");
                wx.hideLoading()
              },
              fail: function(res) {
                console.log("----> 打开文档失败 ");
                console.log(res);
                wx.hideLoading()
                wx.showToast({
                  title: '文档打开失败,请稍后再试!',
                  icon: 'none'
                })
              }
            })
          },
          fail: function(res) {
            console.log("----> 重命名文档失败 " + res);
            wx.hideLoading()
            wx.showToast({
              title: '重命名文档失败,请稍后再试!',
              icon: 'none'
            })
          }
        });
      }
    },
    fail: function(res) {
      console.log(res);
      wx.hideLoading()
      wx.showToast({
        title: '文档打开失败,请稍后再试!',
        icon: 'none'
      })
    }
  })
},

代码较为简单,这里就不一一细说了。细心的小伙伴观察到这里在下载完成后使用了重命名,主要是为了避免打开 PDF 时标题为临时字符,如下所示:

这段代码其实还不是狠完善,最起码提示这块,可以单独封装一层,这里就偷个懒了先。

哦,对,还有一点,云平台 PDF 地址记得拷贝下载地址哈!

5. 改造 vant-tabs 实现放大/缩小 tab 切换

先来看个效果吧,Android 那边现成的 TabLayout 及其方便快捷,到了这边,哎。

怪我,不懂前端。

没啥说的,基于 vant-tabs 改造即可,下面直接附上完整代码。

<van-tabs active="{{ active }}" 
  animated swipeable 
  nav-class="nav-class" 
  tab-class="tab-class" 
  tab-active-class="tab-active-class">
  <van-tab title="游艇产业介绍">
    123
  </van-tab>
  <van-tab title="游艇产业政策">
    123
  </van-ta>
  <!-- ... -->
</van-tabs>

样式文件如下:

.van-ellipsis {
  margin: 6rpx 0rpx 6rpx 14rpx;
}

.tab-class {
  display: contents !important;
  padding: 0 12px !important;
  color: var(--tab-text-color, #646566) !important;
  font-size: var(--tab-font-size, 14px) !important;
  line-height: var(--tabs-line-height, 112rpx) !important;
}

.tab-active-class {
  font-weight: var(--font-weight-bold, 800);
  font-size: var(--tab-font-size, 16px) !important;
  color: var(--tab-active-text-color, #323233);
  line-height: 105rpx !important;
}

.nav-class {
  height: auto !important;
  background-color: #f5f5f5;
}

除了第一个样式比较特殊,剩下都是按照官方提供的自定义样式而来,这里简单截图说明下,便于日后查看:

6. 如何实现 tabs 内容高度充满屏幕?

要在 tabs 中嵌套一个地图,按道理来讲设置宽高 100% 就应该是充满屏幕了,结果是这个惨样子:

下面还是空余了很大的空间,突然想到之前 PHP 使用过的 vh,据说是动态屏幕大小,调整后如下:

map {
  width: 100%;
  height: 94.5vh;
}

这样就能充满整个屏幕咯。小伙伴可以想想为什么不设置 100vh?

7. 如何实现 text 最多显示两行,超出 ... 显示?

样式如下:

.item_action_title { 
  display: -webkit-box;  
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  overflow: hidden;
  text-overflow: ellipsis;
  text-overflow: -o-ellipsis-lastline;   
}

8. 如何在 map 上添加对应浮层?

先来看下最终的效果:

这里 diss 下微信小程序官方神逻辑,明明我在模拟器一通操作猛如虎,为何运行真机不显示?逗我玩呢?为什么不直接在模拟器上禁止呢?好玩吗?

先说几点注意事项吧:

  • map 组件是由客户端创建的原生组件,它的层级是最高的 (也就是说不支持在 map 上使用常规方式添加内容);
  • cover-view 只支持嵌套 cover-view、cover-image,可在 cover-view 中使用 button。组件属性的长度单位默认为 px,2.4.0 起支持传入单位(rpx/px);
  • cover-image 直到现在(2020-10-23)不支持 mode,图片缩放模式。

首先来看下我这里简单模拟的数据格式:

portList: [{
      title: '会所 - 001',
      desc: '会所介绍',
      avatar: 'http://www.china-rendezvous.com/Index/Tpl/Public/images/index/banner.jpg'
    }, {
      title: '会所 - 002',
      desc: '会所介绍',
      avatar: 'http://www.china-rendezvous.com/Index/Tpl/Public/images/index/banner.jpg'
    }, {
      title: '会所 - 003',
      desc: '会所介绍',
      avatar: 'http://www.china-rendezvous.com/Index/Tpl/Public/images/index/banner.jpg'
    }, ]

随后附上 map 关键代码:

<map setting="{{ setting }}">
  <cover-view class="port_class">
    <block wx:for="{{ portList }}" wx:key="port">
      <cover-view class="item_port">
        <cover-view class="item_port_content">
          <cover-view class="title">{{ item.title }}</cover-view>
          <cover-view class="desc">{{ item.desc }}</cover-view>
        </cover-view>
        <cover-image src="{{ item.avatar }}" />
      </cover-view>
      <cover-view class="divider_line" wx:if="{{ index < portList.length - 1 }}" />
    </block>
  </cover-view>
</map>

对应 js:

// 地图基本配置
setting: {
  skew: 0, // 倾斜角度
  rotate: 0, // 旋转叫丢
  scale: 8, // 缩放级别,取值范围为3-20  
  showLocation: true, // 显示带有方向的当前定位点
  showScale: true, // 显示比例尺
  subKey: '', // 个性化地图使用的key
  layerStyle: 1, // 个性化地图配置的 style,不支持动态修改
  longitude: 109.76685421005249,
  latitude: 19.207716690636587,
  enableZoom: true, // 是否支持缩放  
  enableScroll: true, // 是否支持拖动  
  enableRotate: true, // 是否支持旋转  
  showCompass: true, // 显示指南针  
  enable3D: false, // 展示3D楼块
  enableOverlooking: true, // 开启俯视  
  enableSatellite: false, // 是否开启卫星图  
  enableTraffic: true, // 是否开启实时路况  
  markers: [{
    iconPath: "/images/img_position_flag.png",
    id: 0,
    latitude: 20.045611,
    longitude: 110.181885,
    width: 30,
    height: 30
  }, ],
},

最后的 css 样式文件:

map {
  width: 100%;
  height: 94.5vh;
}

.port_class {
  display: flex;
  flex-direction: column;
  margin: 30rpx;
  background: #fff;
  border-radius: 8rpx;
  position: absolute;
  bottom: 0;
  left: 0;
  right: 0;
  max-height: 45vh;
}

.port_class .item_port {
  display: flex;
  flex-direction: rows;
  padding: 30rpx;
  justify-content: space-between;
}

.port_class .item_port .item_port_content {
  display: flex;
  flex-direction: column;
  flex: 1;
}

.port_class .item_port .item_port_content .title {
  font-size: 30rpx;
  font-weight: bold;
}

.port_class .item_port .item_port_content .desc {
  font-size: 26rpx;
  color: gray;
  margin-top: 22rpx;
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  overflow: hidden;
  text-overflow: ellipsis;
  text-overflow: -o-ellipsis-lastline;
}

.port_class .item_port cover-image {
  height: 120rpx;
  width: 120rpx;
  margin-left: 30rpx;
}

.port_class .divider_line {
  background-color: #f5f5f5;
  width: 100%;
  height: 3rpx;
}

9. 如何实现 map 平移 markers?

记得添加权限,详情查看文末异常汇总。

来看下效果图:

这里附上关键 js 代码:

/**
 * 生命周期函数--监听页面初次渲染完成
 */
onReady: function() {
  this.mapContext = wx.createMapContext('map');
},

/**
 * 港口 item 点击 - 地图 markers 平移
 */
onPortItemClick: function(event) {
  let that = this;
  let currentId = event.currentTarget.dataset.portid; 
  // 获取 markers 目标经纬度
  let destination = {
    longitude: that.data.portList[currentId].longitude,
    latitude: that.data.portList[currentId].latitude
  };
  // 平移 markers
  this.mapContext.translateMarker({
    markerId: 0,
    destination: destination,
    autoRotate: true,
    rotate: 0,
    duration: 1000,
    success(res) {
      console.log('---> 平移成功 ', res)
    },
    fail(err) {
      console.log('---> 平移失败 ', err)
    }
  });
}

哦,对了,html 文件如下:

<map id="map" setting="{{ setting }}" />

10. 如何平移 markers 到地图中心?

记得添加权限,详情查看文末异常汇总。

html 文件如下:

<map id="map" setting="{{ setting }}" show-location />

关键 js 代码如下:

/**
 * 港口 item 点击 - 地图 markers 平移
 */
onPortItemClick: function(event) {
  let that = this;
  let currentId = event.currentTarget.dataset.portid;
  // 平移 markers 到地图中心
  this.mapContext.moveToLocation({
    longitude: that.data.portList[currentId].longitude,
    latitude: that.data.portList[currentId].latitude,
    success(res) {
      console.log('---> 平移成功 ', res)
    },
    fail(err) {
      console.log('---> 平移失败 ', err)
    }
  });
}

11. 关于标题设置静态/动态

一般而言,对于某些固定的页面,我会直接在页面对应的 json 文件指定:

"navigationBarTitleText": "详情",

而某些动态,则通过如下方式进行动态设置:

// 设置标题
wx.setNavigationBarTitle({
  title: portBean.title,
});

12. 关于获取用户公开信息

我这里用的是 vant-button 和 button 没啥区别,内容如下:

<van-button 
    wx:if="{{ avatarUrl }}" 
    open-type="getUserInfo" 
    bindgetuserinfo="bindGetUserInfo" 
    color="#1497da" 
    custom-class="login" round type="info">登录/注册</van-button>

对应的 js:

/**
 * 生命周期函数--监听页面加载
 */
onLoad: function(options) { 
  wx.getSetting({
    success: function(res) {
      if (res.authSetting['scope.userInfo']) {
        wx.getUserInfo({
          success: function(res) {
            console.log(res); 
          }
        })
      }
    }
  })
},

/**
 * 获取用户信息
 */
bindGetUserInfo: function(res) { 
  console.log(res); 
},

获取到的数据:

首次会弹个框,如下:

13. 如何在地图上绘制覆盖物?

先来看下效果:

再来看一波官方 Api:

附上 wxml 代码:

<map id="map" setting="{{ setting }}" 
  scale="15" 
 show-location polygons="{{polygons}}" />

以及对应的 js 文件:

首先我们定义一个存放坐标点的 list:

const mTempWaterPolygonsList = [{
  points: [{
      longitude: 110.2100,
      latitude: 20.0449
    },
    {
      longitude: 110.2100,
      latitude: 20.0651
    },
    {
      longitude: 110.3100,
      latitude: 20.0653
    },
    {
      longitude: 110.3101,
      latitude: 20.0104
    },
  ],
  strokeColor: "#333",
  strokeWidth: 3,
  fillColor: "#80333333"
}, {
  points: [{
      longitude: 110.4036,
      latitude: 19.1908
    },
    {
      longitude: 110.4300,
      latitude: 19.1759
    },
    {
      longitude: 110.3457,
      latitude: 19.0230
    },
    {
      longitude: 110.3401,
      latitude: 19.0246
    },
  ],
  strokeColor: "#333",
  strokeWidth: 3,
  fillColor: "#80333333"
}, ];

初始化 map 基本设置:

data: {
  // 地图基本配置
  setting: {
    skew: 0, // 倾斜角度
    rotate: 0, // 旋转角度
    scale: 11, // 缩放级别,取值范围为3-20  
    showLocation: true, // 显示带有方向的当前定位点
    showScale: true, // 显示比例尺
    subKey: '', // 个性化地图使用的key
    layerStyle: 1, // 个性化地图配置的 style,不支持动态修改 
    longitude: 110.260025,
    latitude: 20.046425,
    enableZoom: true, // 是否支持缩放  
    enableScroll: true, // 是否支持拖动  
    enableRotate: true, // 是否支持旋转  
    showCompass: true, // 显示指南针  
    enable3D: false, // 展示3D楼块
    enableOverlooking: true, // 开启俯视  
    enableSatellite: false, // 是否开启卫星图  
    enableTraffic: false, // 是否开启实时路况  
  }, 
  // 默认绘制第一个覆盖物
  polygons: [{
    ...mTempWaterPolygonsList[0]
  }, ],
},

而关于点击绘制其它覆盖物时,只需要动态更新 polygons 即可,例如我这里的操作:

/**
 * item click
 * Step 1: 平移中心点到地图中心;
 * Step 2: 绘制点对应覆盖物
 */
onWaterItemClick: function(event) {
  let that = this;
  let currentId = event.currentTarget.dataset.waterid;
  // Step 1: 平移中心点到地图中心;
  this.mapContext.moveToLocation({
    longitude: that.data.tempWaterList[currentId].centerLongitude,
    latitude: that.data.tempWaterList[currentId].centerLatitude,
    success(res) {
      console.log('---> 平移成功 ', res)
    },
    fail(err) {
      console.log('---> 平移失败 ', err)
    }
  });
  // Step 2: 绘制点对应覆盖物
  let polygons = mTempWaterPolygonsList[currentId];
  that.setData({
    'polygons[0]': polygons,
  });
},

End

十多条整理下来,也是一段小经历。

微薄之力,助力和我一样小白~

一起加油~

万一不小心优秀了呢?

异常汇总

  • oveToMapLocation:fail require permission desc

官方说明:获取用户位置信息时需填写用途说明

在 app.json 中添加获取位置权限:

"permission": {
  "scope.userLocation": {
    "desc": "您的位置信息将用于小程序地图的效果展示"
  }
},

参考资料

  • 微信官方开发文档
  • Vant Weapp

本文分享自微信公众号 - 贺利权(hlq_struggle),作者:贺利权

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2020-10-28

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 「微信小程序」开发常用事例(六)

    将自己经历的一些问题记录在案,方便后续类似相同需求直接使用“CV 大法”,节省部分开发成本。当然,如果此文某一条正好对屏幕前的你有所帮助,点个小赞赞,我会贼老开...

    HLQ_Struggle
  • 微信开发--微信小程序(三)

    将数据存储在本地缓存中指定的 key 中。会覆盖掉原来该 key 对应的内容。数据存储生命周期跟小程序本身一致,即除用户主动删除或超过一定时间被自动清理,否则...

    生南星
  • 微信小程序常见事例 Note(One)

    LZ-Says:不走,总会被逼着走。想要拥有 Change 的权利,背后需要付出更多_____

    HLQ_Struggle
  • 微信小程序开发-常见问题

    知晓程序员,专注微信小程序开发的程序员! 好久没写文章,今天总结一下小程序开发过程中遇到的问题,有不对的地方,欢迎各位指正~ 1、域名必须是HTTPS 非HT...

    连胜
  • 微信小程序开发-常见问题

    知晓程序员,专注微信小程序开发的程序员! 好久没写文章,今天总结一下小程序开发过程中遇到的问题,有不对的地方,欢迎各位指正~ 1、域名必须是HTTPS2、inp...

    企鹅号小编
  • 微信小程序开发

    要求开发者有一些前端知识(HTML,CSS ,JavaScript), “工欲善其事必先利其器”,我们得先:

    狂奔的小马
  • 微信开发--微信小程序(二)

    相信大家都使用过微信小程序,那一定都知道微信小程序下拉刷新吧,其实下拉刷新是微信小程序自带的功能,只不过没有背景图看不出来而已,好坑诶.

    生南星
  • 微信开发--微信小程序(一)

    微信小程序开发相对于微信公众号的开发显得更为重要,下面就来简单介绍一下微信小程序的开发.

    生南星
  • 微信开发--微信小程序(四)

    1.小程序向后台请求接口必须使用https,包括web-view里的网页,如果项目中有用到web socket,那么也必须使用wss协议。https证书一般会用...

    生南星
  • 微信小程序发送模版消息(事例)

    honey缘木鱼
  • 微信小程序开发工具 微信小程序平台开发小程序公司

    小程序倡导更加便捷的生活服务理念,无需下载,唾手可得,即用即走,未来,普通人的生活里,小程序将无处不在。

    微信小程序开发加盟服务商
  • 微信小程序开发系列教程三:微信小程序的调试方法

    这个教程的前两篇文章,介绍了如何用下图所示的微信开发者工具自动生成一个Hello World的微信小程序,并讲解了这个自动生成的微信小程序的视图开发原理。

    Jerry Wang
  • 微信小程序开发系列教程三:微信小程序的调试方法

    版权声明:本文为博主汪子熙原创文章,未经博主允许不得转载。 https://jerry.bl...

    Jerry Wang
  • 微信小程序开发常见问题(六)

    知晓程序员,专注微信小程序开发的程序员! 一、登录实现 小程序登录的实现,官方建议自己保存用户登录状态,不要频繁调用wx.login,否则会限制登录。 这里连...

    连胜
  • 微信小程序开发常见问题(五)

    知晓程序员,专注微信小程序开发的程序员! 一、微信小程序审核未通过,怎么办? 小程序审核不通过的原因很多,微信会给出相应审核不通过 的原因。今天连胜老师给大家...

    连胜
  • 微信小程序开发常见问题(四)

    知晓程序员,专注微信小程序开发的程序员! 一、小程序不同页面之间的传值方式 a、URL传值 这种方式最常用,比如: wx.navigateTo({ url...

    连胜
  • 微信小程序开发常见问题(二)

    知晓程序员,专注微信小程序开发的程序员! 今天再给大家分享几个微信小程序开发的常见问题,顺便吐槽一下,武汉的冬天太TM冷了,没有暖气的冬天真的很难过,写文章的心...

    连胜
  • 微信小程序开发常见问题(七)

    知晓程序员,专注微信小程序开发的程序员! 一、判断小程序版本号 小程序的API是不断更新的,你可能使用某个API时,文档里会说明,此API在1.x.x版本开始...

    连胜
  • 微信小程序二维码实例开发

    开始 小编初学微信小程序,想做一个二维码生成器;作为一个小白,踩了不少坑,在这里分享给大家“如何在微信小程序上生成二维码”。 步骤 就像写前端代码一样,html...

    benny

扫码关注云+社区

领取腾讯云代金券