uni-app微信小程序开发

1,233 阅读3分钟

uni-app是使用vue框架结合微信小程序以及其他平台特性和渲染机制开发出来的跨平台的框架,所以在开发的过程中推荐使用vue的语法。

以下则记录了uni-app区别于vue开发以及微信小程序原生开发的一些点:

区别于vue开发:

  1. v-model无法在除了input等默认为change或input的触发事件使用,目前这个问题还没找到解决方法,还是使用.sync来处理
  2. 不支持自定义指令
  3. 不支持transform过度动画标签的使用,可使用css或者animation的api
  4. 不支持keep-alive
  5. v-html标签会自动转化为rich-text标签
  6. 组件样式穿透,使用/deep/无效,可添加属性如下属性
export default {
  options: { styleIsolation: 'shared' },
}

区别于原生小程序开发:

  1. 组件需要监听父页面的生命周期的时,使用onPageShow,onPageHide,onPageResize代替,而不是使用原生小程序的onPageLifeTimes
  2. 引入的wxs文件放在文件的最后面,因为在vue单文件中只有一个script标签,而wxs如果在前面,会默认按照第一个script去做索引,会使eslint以及一些跳转出错,所以建议写在最后方。
  3. 停止使用behaviors,换用mixin
  4. 标签中如果属性和class是通过数组的长度来动态变化的,如<view :class='active: lits.length'>,如果这样写是不会根据数组变化而生效的,有两种建议写法,一种是转换类型如<view :class='active: Number(lits.length) !== 0'>或者<view :class='active: Boolean(lits.length)'>,另一种是使用计算函数,如下:
<view :class='active: listLength'>
	computed: {
		listLength () {
			return this.list.length
		}
	}
  1. 查找组件不要使用selectComponent,而是使用$ref
  2. 不支持<template name='test'>111</template><template is='test'></template>模板语法的使用,如需使用模板,则可写成组件的形式
  3. 抽象节点componentGenerics不支持,但是也不支持vue的动态组件,所以只能引入组件按逻辑判断了

uni-app开发建议:

  1. 使用 createIntersectionObserver代替onScroll方法。在开发中,我们经常会遇到一些判断交界的情况,比如说判断某个元素是否完整出现在屏幕上,判断某个元素是否被遮盖,判断是否置顶。以往都是通过scroll-viewscroll方法回调去做监听,这样对性能来说很不好,特别是一些只是为了埋点,无任何用户交互的地方。建议使用IntersectionObserver边界监听来处理,已节省性能开销。

tips:本方法无法在父组件创建,然后监听子组件里的元素,但是可以在子组件监听父组件,常规使用问题不大。

详细博客链接:blog.csdn.net/hahahhahaha…

示例代码:

<view
v-for="item in datum.thematicListSimilarLists"
:key="item.id"
class="list-similar-item flex-x-between"
@click="handleToListDetail(item.id, item.name)"
:id="`similar-${item.id}`"
>
<view class="name">{{item.name}}</view>
<view class="num flex-y-center">
  <text>{{item.productCount}}款</text>
  <text class="iconfont icon-personal-arrow"></text>
</view>
</view>

// 相似榜单曝光埋点
trackSimilarListShow () {
  this.$nextTick(() => {
    const observer = wx.createIntersectionObserver(this, {
      observeAll: true
    })
    observer.relativeToViewport({ bottom: -rpx2px(100) }).observe('.list-similar-item', (res) => {
      if (res.intersectionRatio > 0 && res.intersectionRatio <= 1) {
        const id = res.id.split('-')[1]
        if (!this.reportedSimilar.includes(id)) {
          // 未上报
          this.reportedSimilar.push(id)
          const topicName = this.datum.thematicListSimilarLists.filter(item => item.id === id)[0].name
          this.trackTopicListPageSimilarShow({
            topic_list_id: this.id,
            topic_list_name: this.datum.name,
            similar_topic_name: topicName
          })
        }
        if (this.reportedSimilar.length === this.datum.thematicListSimilarLists.length) {
          // 全部已上报 关闭监听节省资源
          observer.disconnect()
        }
      }
    })
  })
}

uni-app开发需要注意的点:

  1. 所有需要手动操作scrollLeft、scrollTop的时候,如果一直设置为相同值如 this.setData({left: 0})会导致除了第一次意外均无效,这是由于传参为props单向数据流,每次设置同样值时,会做diff处理从而不会变化。
  2. 组件取名不规范,可能会导致与内置冲突,具体表现为使用$ref获取组件实例时值为undefined。如组件取名为dialog.
  3. 标签或组件传值方法:
// 从原生标签的原生方法获取
<view @tap='handler'></view>

// 从组件的原生方法获取
<comp-footer @tap.native='handler'></comp-footer>

// 从组件的emit事件获取
<comp-footer @getuserinfo='getuserinfo'></comp-footer>

// 子组件emit一个方法到父组件,方法携带父组件参数
<comp-footer @getuserinfo='getuserinfo' data-info='aaa'></comp-footer>
<script>
getuserinfo(e){
    const { info } = e.currentTarget.dataset;
    let detail = e.detail;
}
</script>
  1. 遇到props传值需要在watch中处理的情况,会出现获取不到,请在watch中追加immediate属性,这是因为小程序原生的observer是默认初始化就监听的。
  2. 如果页面style设置了scoped,page的样式会设置失败,可以在vue页面再写一个style存放,如:
<style>
page{
  background-color: #EDF1F5;
}
</style>
<style scoped>
@import "./xxx.css";
</style>
  1. 当我们在微信小程序 json 中设置 backgroundColor 时,实际在电脑的模拟器中根本看不到效果。这是因为 backgroundColor 指的窗体背景颜色,而不是页面的背景颜色,即窗体下拉刷新或上拉加载时露出的背景。在电脑的模拟器中是看不到这个动作的,所以会让人误以为这个配置是无效的。如果要设置页面背景颜色,得在 wxss 中自定义样式,如下:
page {
    background-color: #eee;
}
  1. 经常会存在一些class是使用wxs并且配合for循环出来动态设置的
<view v-for="i in 10" :class="filter.keys(i) ? 'a':'b' ">xxxxx</view>
<script module='filter' lang='wxs' src='...'></script>

这样使用了循环并且class里使用wxs来做数据渲染,会出现循环的第一个是无法生效,后面的会生效,这种情况目前调试后发现将循环提前能解决。

<template v-for="i in 10">
  <view :class="filter.keys(i) ? 'a':'b' ">xxxxx</view>
</template>
<script module='filter' lang='wxs' src='...'></script>