J'Blog
← 返回文章列表

小程序开发常见问题与解决方案记录

小程序开发常见问题与解决方案记录

小程序开发常见问题与解决方案

一、UI布局与样式问题

1. picker-view 选择日期默认选中当前年

在使用 picker-view 组件时,默认选中当前年份需要正确初始化数据。

2. 绝对定位元素显示问题

设置元素为 absolute 绝对定位时,必须指定其相对于哪个元素进行定位,否则元素可能无法正常显示。

3. 头部栏与底部安全区域处理

需要考虑不同设备的安全区域,特别是全面屏设备:

// 获取菜单按钮位置信息
wx.getMenuButtonBoundingClientRect()

// 底部安全区域处理
margin-bottom: env(safe-area-inset-bottom)

4. 元素吸顶实现

使用 position: sticky 实现吸顶效果:

// 页面滚动监听
onPageScroll: function(e) {
  const scrollTop = e.scrollTop
  // 根据滚动距离判断是否吸顶
  if (scrollTop > (this.data.menuButton.bottom)) {
    this.setData({
      opacity: (scrollTop - this.data.menuButton.bottom) / this.data.menuButton.bottom
    })
    return
  }
  this.setData({
    opacity: 0
  })
}

二、组件交互与数据传递

1. 父子组件传值

小程序中父子组件传值遵循特定规则:

  • 父→子:通过属性传递
  • 子→父:通过事件绑定
// 父组件
<child-component binddateChange="dateChange"></child-component>

// 子组件
bindChange(e) {
  const val = e.detail.value
  this.triggerEvent('dateChange', {
    date: `${this.data.years[val[0]]}-${this.data.months[val[1]]}-${this.data.days[val[2]]}`,
    fieldName: this.properties.type
  })
}

// 父组件接收
dateChange(e) {
  this.setData({
    info: {
      ...this.data.passportInfo,
      [e.detail.fieldName + 'Label']: e.detail.date,
      [e.detail.fieldName]: new Date(e.detail.date.replace(/-/g, '/')).getTime()
    }
  })
}

2. data-*属性获取

通过 data-* 获取属性值时,值可能在 target 或 currentTarget 中,需根据实际情况选择。

3. 条件渲染与循环渲染

小程序提供了条件渲染和循环渲染的指令:

<!-- 条件渲染 -->
<view wx:if="{{condition}}">显示内容</view>
<view wx:elif="{{condition2}}">其他内容</view>
<view wx:else>默认内容</view>

<!-- 循环渲染 -->
<view wx:for="{{list}}" wx:key="index" data-index="{{index}}" data-item="{{item}}">
  {{item.name}}
</view>

三、页面导航与跳转

1. 页面跳转方法

// 跳转到新页面
wx.navigateTo({ url: '/pages/detail/detail' })

// 返回上一页
wx.navigateBack({
  delta: 1,
  fail: _ => {
    wx.switchTab({ url: '/pages/home/home' })
  }
})

// 跳转到tab页面
wx.switchTab({ url: '/pages/home/home' })

2. 页面滚动控制

// 滚动到指定位置
wx.pageScrollTo({
  scrollTop: 0,
  duration: 300
})

3. scroll-view 滚动视图

使用 scroll-view 实现横向滚动:

<scroll-view class="scroll" scroll-x show-scrollbar="{{false}}" scroll-with-animation="{{true}}" scroll-left="{{scrollLeft}}">
  <view class="list">
    <view bind:tap="activeTabHandle" class="tab-item {{activeIndex === index ? 'active' : ''}}" wx:for="{{actInfo.tabInfo}}" wx:key="index" data-index="{{index}}" data-item="{{item}}">
      <image src="{{filters.resizeImage(item.flowerImage ,{width:60}, 'jpg')}}" mode="widthFix" />
      <text>{{item.categoryName}}</text>
    </view>
  </view>
</scroll-view>

4. 原生左右切屏

使用 transform 实现原生左右切屏效果:

<view style="display: flex;transition: all 1s; transform: translateX(calc(-{{activeIndex}}*100vw));width: {{actInfo.tabInfo.length*100}}vw">
  <view class="item" wx:for="{{actInfo.tabInfo}}" wx:key="index" data-item="{{item}}" style="height: {{activeIndex === index ? 'fit-content': '0'}}">
    内容区域
  </view>
</view>

四、图片处理与预览

1. image 组件使用

image 组件的 mode 属性可以控制图片显示方式:

<image src="" mode="widthFix" bindtap="previewImage" data-url="{{item.value}}" />

// 图片点击预览
previewImage: function (e) {
  const currentUrl = e.currentTarget.dataset.url
  wx.previewImage({
    current: currentUrl,
    urls: this.properties.list
  })
}

五、API使用与兼容性处理

1. 日期格式兼容性

iOS 不支持 "2024-12-27" 这样的日期格式,需要将 - 替换成 /:

new Date(dateString.replace(/-/g, '/'))

2. 打开公众号文章

// 直接打开
wx.openOfficialAccountArticle({
  url,
  success: res => {},
  fail: res => {}
})

// 兼容方案:使用 webview
<web-view src="{{url}}"></web-view>

3. 微信内置地图

wx.openLocation({
  name,
  address,
  latitude,
  longitude,
  scale: 18
})

4. 其他常用API

// 打电话
wx.makePhoneCall({
  phoneNumber: phone
})

// 选择收获地址
wx.chooseAddress({
  success(res) {
    // 选择收获地址回调函数  
  }
})

// 联系客服
<button open-type="contact">联系客服</button>

六、分享功能实现

1. 分享给朋友

// 页面分享
async onShareAppMessage(e) {
  return {
    title,
    path,
    imageUrl
  }
}

// 分享到朋友圈
onShareTimeline() {
  return {
    title,
    query,
    imageUrl
  }
}

// 隐藏分享按钮
wx.hideShareMenu({
  menus: ['shareTimeline']
})

2. 直播间分享

直播间内点击商品跳转到商品详情页面会自带用户openid和room_id:

// 商品详情页分享直播间
let path = 'plugin-private://{appid}/pages/live-player-plugin?room_id=' + this.data.options?.room_id
const customParams = encodeURIComponent(JSON.stringify({ share_openid: this.data.options?.openid }))
path += `&custom_params=${customParams}`

// 在小程序app.js中监听路由判断是否在直播间
const livePlayer = requirePlugin('live-player-plugin')
const liveInfo = await livePlayer.getShareParams()
if (!liveInfo.share_openid) liveInfo.share_openid = liveInfo.custom_params?.share_openid

七、性能优化与埋点

1. 埋点统计

// 事件埋点
wx.reportEvent(string eventId, object data)

2. scroll-view与页面滚动事件

scroll-view 滚动视图和页面原生监听滚动事件不能同时使用,如果使用了 scroll-view 就要使用组件内部的监听事件监听页面滚动,同时不能使用原生方法指定页面滚动到具体位置。

八、其他实用技巧

1. markdown文本渲染

<rich-text class="ich-text" nodes="" />

2. 获取自定义组件实例

// 获取自定义组件的实例
const tabInfoComponent = this.selectComponent('#tabInfoComponent')
// 调用组件的方法
tabInfoComponent.getElementInfo()

3. 获取元素位置信息

getComponentHeight() {
  let rect = []
  const query = wx.createSelectorQuery().in(this)
  this.data.tabs.forEach((tab, index) => {
    query.select(`#section${index}`).boundingClientRect()
  })
  query.exec(res => {
    rect = res.map(item => {
      if (item) return item.top + this.data.scrollTop
      else return 0
    })
    this.setData({
      componentPositions: rect
    })
  })
}

以上是小程序开发过程中常见的问题及解决方案,希望对开发者有所帮助。在实际开发中,还需结合微信小程序官方文档和具体业务需求进行灵活应用。