uni-app开发小结

641 阅读5分钟

使用uni-app开发初体验

image.png

使用HBuilder X开发快捷键的使用及对vue的适配支持体验

一、多端支持的全局引入组件方法

问题描述: 在所有页面中增加功能性全局按钮

问题解析:

  1. 不需要在app.vue里添加router-view,这没法实现多端;
  2. 不需要在main.js使用document,这也没法实现多端;
  3. app端不需要创建新的窗口,效果不好,也没法实现多端 主要思路:通过创建一个总组件,把它当做所有页面的大盒子,利用插槽实现。
    实现步骤:
  4. 在components文件夹下创建page组件(组件名随意),在该组件内写上基本每个页面都能用上的组件和方法;
  5. 在main.js引入
<template>
    <view class="globalpage">
        <slot></slot>
        
        <view class="globalpage-other">
            <!-- 页面中的其他内容 -->
        </view>
    </view>
</template>
// 引入
import Page from './components/page.vue'; 
Vue.component('page', Page)
  1. 在你想使用总组件的页面下使用,template下应该是view,这时候把view改成page(带上ref方便操作),接下来就可以随心所欲的使用全局组件了。
<template>
    <page ref="pageGlobal">
        <!-- 这里写代码,会被放置在globalpage中 slot 定义的位置 -->
    </page>
</template>

二、创建.gitignore文件

新创建的文件目录中不包含.gitignore文件,可以在项目根目录中新建一个,具体步骤如下:

  1. 在项目根目录下执行cmd,新建.gitignore文件
touch .gitignore

如果遇到报错提示:‘touch’ 不是内部或外部命令,也不是可运行的程序 或批处理文件。 可以改用如下命令行进行创建:

echo test>.gitignore

这时在项目根目录中就可以看到新建的.gitignore文件夹了

  1. 把不需要提交到git上面的文件提交进去
node_modules/
.project
unpackage/
.DS_Store

image.png

  1. 如果项目在之前提交过以上文件(如unpackage),则需要执行以下命令:
git rm -r --cached unpackage
  1. 执行完成后,重新提交代码即可。

三、常见业务需求开发

1. 判断登录设备
uni.getProvider({
	service: 'oauth',
	success: (res) => {
	   if (res.provider.indexOf('weixin') > -1) {
                this.provider = 'weixin'
	   } 
	},
	complete: () => {
					
	}
})		
2. 自定义头部导航栏
<template>
        <view class="navBarWarp" :style="{height:navHeight+'px'}">
            <view class="navBar" :style="{marginTop:searchMarginTop+'px',width:searchWidth+'px'}">
                <view class="navBarName" :style="{lineHeight:searchHeight+'px'}">{{title}}</view>
                <view class="searchGroup" :style="{width: searchBtnWidth, height:searchHeight+'px'}">
                    <image src="/static/images/home/search.png" class="searchImage" />
                    <input class="searchInput" placeholder="请输入关键字搜索"/>
                </view>
            </view>
        </view>
</template>
<script>
        export default {
            props: ['title'],
            data () {
                    return {
                            navHeight: '',
                            menuButtonInfo: {},
                            searchMarginTop: 0,
                            searchWidth: 0,
                            searchHeight: 0,
                            searchBtnWidth: '60%'
                    }
            },

            created() {
                    this.menuButtonInfo = uni.getMenuButtonBoundingClientRect()
                    const { top, width, height, right } = this.menuButtonInfo
                    const statusBarHeight = uni.getSystemInfoSync().statusBarHeight
                    const margin = top - statusBarHeight
                    this.navHeight = height + statusBarHeight + (margin * 2)
                    this.searchMarginTop = statusBarHeight + margin +3
                    this.searchHeight = height-6
                    this.searchWidth = right - width

                    if(this.title.length == 4) this.searchBtnWidth = '50%'
            }
        }
</script>

<style lang="scss" scoped>
    .navBarWarp{
            width:100%;
            position: fixed;
            left: 0;
            top: 0;
            background: #846efd;
            z-index: 999;
            .navBar{
                    display: flex;
                    flex-direction: row;
                    justify-content:space-between;
                    width: 100%;
                    color:#ffffff;
                    .navBarName{font-size: 16px;margin:0 0 0 24rpx;}
                    .searchGroup {
                        position:relative;					
                        background-color: #ffffff;
                        display: flex;
                        justify-content: space-between;
                        align-items: center;
                        border-radius: 60rpx;
                        padding: 0 30rpx;
                        margin-right:30rpx;
                        .searchInput {
                              font-size: 12px;
                              margin-left: 40rpx;
                              color:#999999;
                        }
                        .searchImage {
                             position:absolute;  
                             height: 32rpx;
                             width: 32rpx;
                        }
                    }
            }
    }	
</style>
3.下拉刷新,上拉加载

方法一 z-paging下拉刷新、上拉加载更多

方法二、使用uniapp 相关配置和对应生命周期实现

首先我们要知道,uniapp的上拉加载和下拉刷新一样都存在两种情况,一个是整体的上拉(生命周期函数 onReachBottom 实现), 一个是局部的上拉(基于 scrpll-view 组件实现);

因为列表内容嵌套出现问题,导致 onReachBottom 事件无法被触发,记住:列表内容如果是组件,外层不需要再包裹一层,即列表项必须是页面内容的第一层级。这就是整体的上拉

scrpll-view 实现局部的下拉,代码实现在下面

整体的下拉

// 在 pages.json 中配置
"pages": [
    {
        "path": "pages/list/list",
        "style": {
                "navigationBarTitleText": "列表页",
                "enablePullDownRefresh": true, // 开启下拉刷新
                "onReachBottomDistance": 200  // 页面上拉触底事件触发时距页面底部距离,单位只支持px
        }
    }	
]

// 开启后均有对应的生命周期,便可以在相应的页面中进行逻辑处理了。
// 在 list.vue 页面中,与生命周期同级
onPullDownRefresh() {
    console.log("触发了下拉刷新")
    
    setTimeout(() => {
        uni.stopPullDownRefresh()  // 完成刷新,关闭下拉loading 
    }, 2000)
},
onReachBottom() {
    console.log("页面触底了")
},
methods: {
    pullDown() {
        uni.startPullDownRefresh() // 开启下拉
    }
}
// 示例:接口调用实现上拉加载更多和下拉刷新
data() {
    return {
        listData: [],
        pageindex: 1,
        pageSize: 10,
        flag: false
    }
},

onLoad() {
    this.getListData()
},

onPullDownRefresh() {
    console.log("触发了下拉刷新")
    // 数据初始化
    this.pageindex = 1
    this.listData = []
    this.flag = false
    
    // 完成刷新,关闭下拉loading,否则会一直存在
    setTimeout(() => {
        this.getListData(() => {
            uni.stopPullDownRefresh() 
        })
    }, 1000)
},

onReachBottom() {
    console.log("页面触底了")
    // 当加载到全部数据后,给出一个到底标识
    if(this.listData.length < this.pageindex * this.pageSize) return this.flag = true
    this.pageindex++
    this.getListData()
},

methods: {
    async getListData(callBack) {
        const res = await this.$myRequest({
            url: '/api/getlist/pageindex='+this.pageindex
        })
        this.listData = [...this.listData, ...res.data.items]
        callBack && callBack()  // 回调函数,有就执行
    },
}

局部的下拉
#scroll-view# 官方文档

如不触发滚动事件,则可能出现的原因分析如下:

  1. scroll-view组件是局部的滚动, 如果只滚动整个页面, scroll不滚动到底, 就不会触发局部的上拉;
  2. scroll-view组件里的数据太少, 不能进行滚动;
  3. 没有给scroll固定高;
  4. 没有用view将scroll包裹住;
  5. 使用了overflow:hidden;
  6. 没有设置scroll-y;
<scroll-view :scroll-top="scrollTop" scroll-y="true" class="list-content scroll-Y" @scrolltolower="onScrollToBottom">
    <view class="list-content--item">
        // ……
    </view>
    <!-- 很多item 项 -->
    <!-- 到底标识 -->
    <view v-if="flag">------ 我到底啦!------</view>
</scroll-view>
methods: {
    /**
    * 代码实现和 onReachBottom 一样
    */
    onScrollToBottom() {
       // ……
    }
}
4.遮罩层事件穿透解决办法

问题描述:出现遮罩层后,比遮罩层层级低的其他组件依然能滑动滚动
解决方案:直接在需要防止事件穿透的组件标签上加上

:catchtouchmove="true"
5.需要在手机页面上元素跟随手指,用了touchmove,但所有手机都有点卡顿的感觉?

1、用transform:translateY移动,避免直接操作top、margin-top等导致页面频繁reflow
2、touchmove的handler里面,需要执行preventDefault(),屏蔽掉原生滚动

html,body{
  top:0;
  left:0;
  position: absolute;
  -webkit-overflow-scrolling: touch;
  z-index:1;
}
6. 使用索引列表(uni-indexed-list),自定义展示列表

uni-app中页面部分内容使用索引列表(uni-indexed-list),动态数据

四、开发微信小程序遇到的问题

1. Cannot read property 'forceUpdate' of undefined

image.png 原因: 在uni-app里没有配置微信小程序的 AppID
解决: 在项目的 manifest.json 文件中配置已经注册申请的AppID

image.png

2. TypeError: Cannot read property 'call' of undefined

image.png

问题描述:

  1. 时有时无,偶有代码变换就会报错;
  2. uniapp开发,之前是不会的,更新带有热重载的版本后,就出现这种问题。 原因: 未知,一说是因为js和vue不在一起导致的

解决:manifest.json 文件中配置

/* 分包优化 */
"optimization" : {
    "subPackages" : true
},

使用这个配置主要是包太大,加上这个分包的依赖只会打包到分包里,可以看到每个分包都有vendor.js,否则所有的依赖都打包到主包里面,会导致主包的vendor过大;
一般上线的包,可以用"optimization" : { "subPackages" : true}压缩代码,平时开发热更新就不用了。

或者在uniapp重启项目进行解决。

3. 获取用户手机号,提示:getPhoneNumber:fail no permission
<button
   open-type="getPhoneNumber"
   @getphonenumber="getPhoneNumber"
   @click="getPhonenum"
   >立即授权</button>

参考官网 image.png

按照界面提示进行认证,认证时约需要支付300元认证费用。大概需要1-3工作日,认证完成后重新启动IDE,即可。 image.png