【最近更新:2024.2.27】微信小程序前端开发经验总结(不定期更新)

总结记录我在开发微信小程序项目过程中,在前端开发过程中总结的经验和知识点

实现顶部菜单:可横向滚动,且右边渐隐

效果图:可以看出右边的字渐渐隐藏了
在这里插入图片描述

右边渐隐用mask,但是微信小程序要改成-webkit-mask-box-image,mask我试了下是无效的
所以右边渐隐的关键代码是:

-webkit-mask-box-image: linear-gradient(90deg, #000000 90%, transparent);

可以通过调整百分数来调整mask的覆盖宽度,自己该参数看看效果就知道了

还有很关键的一点,这个mask加在哪个css上?答案是:以我下面写的3层为准,要在最外面一层添加,我试了下添加在swtich-wrap中间层是不行的

参考:
小技巧 | 渐变消失遮罩的多种实现方式
mask-image属性小程序失效
我自己的文章

完整代码如下:

<view class="switch">
  <view class="switch-wrap">
    <view wx:for="{{store}}" wx:key="index" class="{{tabValue === item.value ? 'choose' : 'nochoose'}} switch-item" data-id="{{item.value}}" bindtap="onChange">{{ item.label }}</view>
  </view>
</view>
.switch {
  white-space: nowrap;
  overflow: auto;
  width: 65%;   
  -webkit-mask-box-image: linear-gradient(90deg, #000000 90%, transparent);
}

.switch-wrap{
  display: inline-flex;   /* 一定要inline-flex */
  position: relative;
}

.switch-item {
  width: 112rpx;
  height: 56rpx;
  margin-right: 0rpx;
  /* position: relative; */
  display: flex;
  justify-content: center;
  align-items: center;
  font-size: 28rpx;
}
/* 
.switch-item:last-of-type {
  margin-right: 0;
} */


.choose {
  background-color: #F6F7F9;
  border-radius: 200rpx;
  color: #272B3D;
  font-size: 28rpx;
  font-weight: 600;
}

.nochoose {
  color: #BEBEBE;
  font-size: 28rpx;
  font-weight: 400;
}

加载圆圈(会动态旋转)

在这里插入图片描述

    <view wx:if="{{!isEnd}}" class="more-load-bx">
      <view class="loading" />
    </view>

/* 底部更多加载 */
.more-load-bx {
  width: 100%;
  height: 50rpx;
  display: flex;
  flex-direction: column;
  align-items: center;
}

.more-load-bx .loading {
  position: relative;
  width: 40rpx;
  height: 40rpx;
  border: 8rpx solid #F8BF4E;
  border-top-color: rgba(248, 191, 78, 0.1);
  border-right-color: rgba(248, 191, 78, 0.1);
  border-bottom-color: rgba(248, 191, 78, 0.1);
  border-radius: 100%;

  animation: circle infinite 0.75s linear;
}

@keyframes circle {
  0% {
    transform: rotate(0);
  }
  35% {
    transform: rotate(180deg);
  }
  70% {
    transform: rotate(320deg);
  }
  100% {
    transform: rotate(360deg);
  }
}

限制只能输入数字

参考我自己写的文章

去除点击阴影

navigator标签点击会有阴影,去除方法:
全局页面去除(推荐,一键到位,所有页面的都会去除):
在全局的css里加上下面的内容即可去除

.navigator-hover {
	background-color: transparent !important;
	opacity: 1;
}

局部页面去除:
在页面的标签里加上hover-class="none"


<navigator url="/pages/test"  hover-class="none">
	
</navigator>

参考资料


阻止事件冒泡和阻止默认行为

我自己写的文章:阻止事件冒泡和阻止默认行为

自定义渐入渐出动画

如抽屉的渐入渐出:
transition: height 0.3s
秒数可以自己定

js的.map用法

自己的另一篇笔记

异步操作

我自己的文章:JavaScript异步操作

scroll-view标签

设置height:即scroll的长度,如height为100vh,则长度为整个可视区域,有时需要动态计算,此时就可以用到本文后面的wx.createSelectorQuery()函数部分的内容
设置横向还是竖向滚动:scroll-x=“true” / scroll-y=“true”
设置滚动到底部触发函数:bindscrolltolower=" ",常用于分页查询,滚动到底部,触发向后端再次获取分页数据展示
设置下拉刷新:

  • refresher-enabled=“true”:开启自定义下拉刷新
  • refresher-triggered=“{{trigger}}”:设置当前下拉刷新状态,true 表示下拉刷新已经被触发,false 表示下拉刷新未被触发
  • bindrefresherrefresh=“”:自定义下拉刷新触发的函数

官方文档:官方文档

overflow

overflow设置有两种值,一个是hidden,一个是scroll

hidden表示超出可视区域则隐藏
scroll表示超出可视区域则可滚动展示

不设置overflow则默认是overflow: auto(此时超出则scroll)

image标签

图片加载时闪一下再显示的bug,是因为没有设置图片高度,参考:
参考

图片mode可以是:

mode="aspectToFit":缩放模式,保持纵横比缩放图片,使图片的长边能完全显示出来。也就是说,可以完整地将图片显示出来

mode="aspectToFill":缩放模式,保持纵横比缩放图片,只保证图片的短边能完全显示出来。也就是说,图片通常只在水平或垂直方向是完整的,另一个方向将会发生截取。

mode="scaleToFill" :缩放模式,不保持纵横比缩放图片,使图片的宽高完全拉伸至填满 image 元素

mode="widthFix":宽度不变,高度自动变化,保持原图宽高比不变,**再设置想要展示的图片宽度(如UI设计图中给定的宽度,就可以按照UI设计图大小展示图片)**即可

资料:image组件的4种缩放模式与9种裁剪模式, 和静态多文章列表

wxml传参给js

通过点击事件传参(data-)

图片预览js逻辑

可能需要结合 wxml传参给js
官方文档:图片预览官方文档
例如:

在这里插入图片描述
在这里插入图片描述

不同页面之间跳转传参

参考:页面跳转

抽屉弹窗

分为两个部分:

  1. mask
  2. 抽屉本身

动画设置使用官方函数 wx.createAnimation
抽屉动画

每个选项之间的分割线

参考:

抽屉(含动画)

圆角属性

css圆角属性

new promise 函数

参考:new promise
资料

获取用户头像与昵称

参考

自定义组件

参考:

  1. 有数据监听:数据监听
  2. 资料1
  3. 资料2
  4. 资料3

例子:

Component({
  /**
   * 组件的属性列表
   */
  properties: {
    listData: {
      type: Object,
      value: [],
    },
    otherProperty: {
      type: String,
      value: '',
    }
  },
  
  // 监听每个属性值的变化
  observers: {
    'listData': function(newVal) {
      // 处理 listData 属性的变化
      console.log('listData 的新值:', newVal);
    },
    'otherProperty': function(newVal) {
      // 处理 otherProperty 属性的变化
      console.log('otherProperty 的新值:', newVal);
    },
    // 可以继续添加其他属性的观察者函数
  },
  // 其他组件的生命周期函数和方法
});

更具体的示例:

  // 从外部传进组件的值
  properties: {
    listData: {
      type: Object,
      value: [],
    }
  },
  
  // 观察者函数,监听properties中属性值的变化
  observers: {
    'listData': function(newVal){
      if(newVal.length>0 && this.data.goods!==newVal){
        this.setData({
          goods: newVal
        })
        // console.log("Listen data from index");
      }
    }
  },

  /**
   * 组件的初始数据
   */
  data: {
    goods:[]
  },
  
  /**
   * 组件的方法列表
   */
  methods: {
    onChange: function (e) {
      this.triggerEvent('change', e.currentTarget.dataset.id)
    },
  }

父组件向子组件传值

资料

子组件向父组件传值

this.triggerEvent('myevent', myEventDetail, myEventOption)方法

其中参数:
myevent为方法名,
myEventDetail是传到组件外的数据,
myEventOption为是否冒泡的选项,有三个参数可以设置:

bubbles:默认false 事件是否冒泡
composed:默认false 事件是否可以穿越组件边界
capturePhase:默认false 事件是否拥有捕获阶段

大概步骤是:

  • 子组件js中写传值的函数
  • 父组件js中写对传入的值进行相应处理的函数
  • 父组件的wxml相应调用子组件的地方进行bind绑定,格式bind:<子组件传值的函数>=“<父组件处理传入的值的函数>”

示例:

// child.js
// 子组件js中写传值的函数
methods: {
  changeName() {
    this.triggerEvent('changeName', {
      name: '李四'
    })
  }
}
// parent.js
// 父组件js中写对传入的值进行相应处理的函数
handelChangeName(event) {
  console.log(event)
  // { name: '李四' }
}
<!-- parent.wxml -->
<!-- 父组件的wxml相应调用子组件的地方进行bind绑定 -->
<child bind:changeName="handelChangeName" />

一些资料:
资料1
资料2
官方文档:组件传值


wx.createSelectorQuery()方法

注意:在自定义组件或包含自定义组件的页面中,应使用this.createSelectorQuery()

获得某个元素的内容区域上/下边界相对于可视区域(即视窗)顶部的距离

在小程序的wx.createSelectorQuery()方法中,使用 boundingClientRect() 方法查询元素的位置信息时,可以获取到的 res 对象中包含了一些属性,其中包括 top 属性(从元素的内容区域顶部开始到可视区域顶部的距离,下面的bottom同理)。


明确两个概念:

元素的内容区域

元素的内容区域是指元素内部实际承载内容的部分,包括边框(border)、内边距(padding)和外边距(margin)。

可视区域

可视区域是指你可以看得到的页面的区域,所以可视区域顶部就是你现在能看到的页面区域的顶部,区别于页面的顶部。
这对于不会滚动的页面来说可能不好理解,要结合页面滚动来区别。如果一个页面滚动,那么可视区域顶部是现在你能看到的区域的顶部,而页面的顶部是指你页面最开始还没滚动时的那个顶部,所以还需要包括你页面滚动的距离。

wx.getSystemInfoSync().windowHeight; 获得的就是可视区域高度


获得某个元素的内容区域上边界相对于可视区域(即视窗)顶部的距离

示例:假设要获得class="target-element"元素的top属性

var that = this; 
wx.createSelectorQuery().select('.target-element').boundingClientRect().exec(function(res) {
   if (res[0]) {
     var topPosition = res[0].top; // 获取.test元素的上边界位置
     // 得到屏幕除去该元素到顶部后剩下部分的高度
     that.setData({
       height: `calc(100vh - ${topPosition}px)` 
     });
   }
 });
获得某个元素的内容区域下边界相对于可视区域(即视窗)顶部的距离

自然的,bottom属性:元素的内容区域下边界相对于可视区域(即视窗)顶部的距离,和top同理,此处不再赘述


获得某个元素的内容区域高度

注意:获得的高度不包括border、padding和margin。

wx.createSelectorQuery().select('.target-element').boundingClientRect(function(rect) {
  if (rect) {
    var height = rect.height;
    console.log('元素的高度:', height);
  }
}).exec();

记录开发过程中遇到的一个de了很久的bug

在子组件中想获取一个元素的高度(用上面的方法),传给父组件,但是获取到的内容一直为null,debug后发现两个原因:

  1. 在子组件中要用this.createSelectorQuery(),用wx.是错误的
  2. 函数调用要在ready()生命周期中或其之后的生命周期中,否则在这个之前这个元素可能还没渲染出来。导致获取到的内容一直为null(我就一直写在created或attached中,一直不懂为什么null呜呜呜)
    在这里插入图片描述
    资料:
    官方文档:自定义组件组件生命周期
    官方文档:页面生命周期

在微信小程序中使用vantUI

在微信小程序中引入vant组件

想在文字中加空格

  1. text标签
  2. decode="{{true}}
  3. &nbsp;
<text decode="{{true}}">测试&nbsp;测试</text>

呈现的结果:
测试 测试


官方picker选择器(包括官方提供的省市区选择器)

使用picker
picker

列表左滑右滑删除:

使用vantUI组件库的van-swipe-cell
van-swipe-cell 是一个基于 Vue.js 的组件库 Vant(移动端UI组件库)中的组件之一。van-swipe-cell 组件用于实现滑动操作的列表项,类似于滑动删除或滑动展示更多选项的效果。
通过使用 van-swipe-cell 组件,你可以在列表项上进行左滑或右滑操作,显示隐藏的操作按钮或内容。常见的用途包括滑动删除、标记为已读/未读、收藏等。

页面之间传递参数

在跳转url中附上参数(可以序列化,简单参数也可以不序列化)
然后跳转到的页面中的onLoad函数中通过options获取
如:

let url = `/pages/test`
// 参数序列化,加到url中
const params = `?info=${JSON.stringify(e.currentTarget.dataset.item)}`
wx.navigateTo({
  url: url + params
});
onLoad: function(options) {
  // 通过 options 参数获取传递的数据
  // 将字符串解析转为js对象
  const info = JSON.parse(options.info);
  // 使用获取到的数据进行相应的操作
  console.log(info);
}
// 或:options处写成具体的参数名列表,用{}括起来
onLoad: function({info}) {
  // 通过 options 参数获取传递的数据
  // 将字符串解析转为js对象
  const info = JSON.parse(info);
  // 使用获取到的数据进行相应的操作
  console.log(info);
}

也可以采用encodeURIComponent
encodeURIComponent 是 JavaScript 中的一个函数,用于将字符串进行 URL 编码。它将字符串中的特殊字符转换为对应的编码形式,以便在 URL 中传递参数时保证参数的正确性和完整性。encodeURIComponent 函数对该字符串进行编码,确保其中的特殊字符(如可能有?这种)被转义为有效的 URL 字符
这样做的目的是为了将该编码后的参数作为 URL 的一部分,传递给 wx.navigateTo 方法的 url 参数,以便在跳转到 /pages/test页面时,携带和传递该参数。

可以使用 decodeURIComponent 函数来完成解码操作。

如:

let url = /pages/test
const params = ?info=${encodeURIComponent(JSON.stringify(e.currentTarget.dataset.item))}
wx.navigateTo({
url: url + params
});

解码:

onLoad: function(options) {
  const info = JSON.parse(decodeURIComponent(options.info));
  // 使用解码后的参数进行后续操作
  // ...
}

实现网格排列的技巧

在这里插入图片描述

实现图片如上图这样子每3个排一行,主要是想记录一下CSS方面的实现技巧
主要是想说这一段CSS
其中的.img > view:nth-of-type(3n)我觉得是个很好的技巧

<view class='img'>
  <view wx:for="{{tmpImgList}}" wx:key="index">
    <view class='add'>
      <!-- 完成上传 -->
      <image class="delete" src="/static/images/upload_del.png" bindtap='removeImg' data-index='{{index}}' data-src='{{tmpImgList[index]}}'></image>
      <image class='upload' background-size="cover" bindtap='preview' data-url='{{tmpImgList[index]}}' src='{{tmpImgList[index]}}'></image>
    </view>
  </view>
  <view wx:if="{{imgList.length < fileCount}}" class='add' bindtap='addImage'>
    <text class='txt'>{{uploadTip}}</text>
  </view>
</view>

完整CSS代码:

.img {
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-start;
  background: #fff;
}

.img > view {
  margin-right: 30rpx;
}

// 选择.img 的直接子元素中每隔 3 个 view 元素,将这些被选择的 view 元素的右边距设置为 0,即取消其右侧的空白。
.img > view:nth-of-type(3n) {
  margin-right: 0;
}
/* components/uploadImage/uploadImage.wxss */
.img {
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-start;
  background: #fff;
}

.img > view {
  margin-right: 30rpx;
}

// 选择.img 的直接子元素中每隔 3 个 view 元素,将这些被选择的 view 元素的右边距设置为 0,即取消其右侧的空白。
.img > view:nth-of-type(3n) {
  margin-right: 0;
}

.img .add {
  position: relative;
}
.img .add .upload {
  height: 100%;
  width: 100%;
  border-radius: 20rpx;
}

.img .add .delete {
  position: absolute;
  right: 0;
  top: 0;
  height: 32rpx;
  width: 32rpx;
}

.img .add {
  display: flex;
  justify-content: center;
  height: 200rpx;
  width: 200rpx;
  background: #F7F7F7;
  border: 1px solid rgba(190, 190, 190, 0.05);
  margin-bottom: 30rpx;
  border-radius: 20rpx;
}

.img .add .txt {
  margin-top: 84rpx;
  text-align: center;
  display: block;
  color: #BEBEBE;
  font-size: 24rpx;
  line-height: 34rpx;
}

.img .add .icon {
  height: 35rpx;
  width: 35rpx;
  margin-left: auto;
  margin-right: auto;
  display: block;
  margin-top: 7rpx;
}

.img .blur {
  filter: blur(1rpx);
  background-size: cover;
  background-position: center center;
}

.img .loading {
  height: 55rpx;
  width: 55rpx;
  margin-left: auto;
  margin-right: auto;
  display: block;
  margin-top: 35%;
}

view实现网格排列

以每三个一行为例
用到wx:for比较方便
数据(下Card)存在js里,用数组,数组里面可以存一个个{}对象

<view class="card-bg">
   <view class="card" wx:for="{{Card}}">
      <image mode="widthFix" style="width: 36rpx;" src="{{item.img}}"></image>
      <text>{{item.name}}</text>
    </view>
</view>

外面套一层display:flex的容器.card-bg,flex-wrap: wrap; 就会自动换行

每个元素大小在.card里具体设置

可以用**:nth-child(3n)**来设置每3n个(即每行最后一个)的样式,如设置margin-right为0,
类似的还有:last-child是设置所有中的最后一个

/* 重点 */
.card-bg{	
  display: flex;
  flex-wrap: wrap;
  flex-direction: row;
  justify-content: center;
}
.card{
  display: flex;
  justify-content: center;
  align-items: center;
  width: 195rpx;
  height: 80rpx;
  border-radius: 20rpx;
  background-color: #f7f7f7;
  margin-right: 16rpx;
  margin-top: 30rpx;
}
.card:nth-child(3n){	// 注意是card而不是套在外面的card-bg,指定第3、6、9...3n个元素的样式
  margin-right: 0rpx;
}

.dazi-card:nth-child(-n+3){		// 指定前三个元素的样式
  margin-top: 0rpx;
}

.dazi-card:nth-last-child(-n+3) {	// 倒数三个元素
  /* 样式规则 */
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值