HBuilderX

HBuilderX

极客开发工具
uni-app

uni-app

开发一次,多端覆盖
uniCloud

uniCloud

云开发平台
HTML5+

HTML5+

增强HTML5的功能体验
MUI

MUI

上万Star的前端框架

寻unickoud 开发经验丰富的高手。

uniCloud

有时间可以远程兼职或长期合作。
要求有uniapp+ unicloud 开发经验,最好使用过vkadmin 。

联系QQ 12040、126.

有时间可以远程兼职或长期合作。
要求有uniapp+ unicloud 开发经验,最好使用过vkadmin 。

联系QQ 12040、126.

uni-app的官方文档太难用了!

文档

如题,uni-app的官方文档对新接触uni-app的人来说,太不友好了,找个东西都很麻烦。
如,要找组件相关文档,还得去“页面”这个左侧菜单里去找。关键找到之后,感觉写得不清不楚的。
我要找uni-app组件的生命周期,可找到一看,只有vue的生命周期,并没有标注和其它各端小程序生命周期的对应关系。包括页面生命周期也一样没标注,只是页面生命周期基本和小程序差不多,还好理解。
原生小程序的一些特性支不支持也不说,看得云里雾里的。
感觉把vue的文档放进来没有太大意义,你们只需要说明和vue的区别应该就可以。
官方能把文档归类整理以及详细补充一下吗?

继续阅读 »

如题,uni-app的官方文档对新接触uni-app的人来说,太不友好了,找个东西都很麻烦。
如,要找组件相关文档,还得去“页面”这个左侧菜单里去找。关键找到之后,感觉写得不清不楚的。
我要找uni-app组件的生命周期,可找到一看,只有vue的生命周期,并没有标注和其它各端小程序生命周期的对应关系。包括页面生命周期也一样没标注,只是页面生命周期基本和小程序差不多,还好理解。
原生小程序的一些特性支不支持也不说,看得云里雾里的。
感觉把vue的文档放进来没有太大意义,你们只需要说明和vue的区别应该就可以。
官方能把文档归类整理以及详细补充一下吗?

收起阅读 »

实现pages路由跳转url的ts类型检查(上)

uniapp

我目前使用的是参考官方vue3+ts+vite的cli模板示例,去除暂时不涉及到的平台的npm依赖,这样就能够使用eslint+prettier等工具链以及vscode实现更贴近传统web开发的开发体验。整体运行良好,即使需要用插件库也可以通过下载解压对应包到本地实现,唯二有个两问题一直不能很好的解决,其一就是路由跳转的类型校验。

uniapp沿用和对齐微信小程序的pages.json来实现页面路由的控制,hbuilderx可以实现一部分跳转的路由提示,但还是不够完善,且不能对无效路由做错误提示。经过几次尝试,最后终于实现了一个完美的解决方案。

最开始的时候是想通过自己封装下路由,然后import pages.json中的数据结构,去实现路由的类型校验。但是因为ts对于json的解析是直接解析成了string这个比较宽泛的类别,且无法通过类型推断(as const)去实现,详见https://github.com/microsoft/TypeScript/issues/32063

既然无法通过json实现类型推断,那么可以转换下思路,通过ts去配置pages,但是uniapp不兼容这种方案。那么可以再进一步,通过ts配置pages,在执行uniapp的构建命令前根据这个pages.ts去生成pages.json。

理想很丰满,现实很骨感,这个思路的方向是对的,然而在实现pages.ts输出到pages.json出现了好多问题。迎面而来的是:这段逻辑(下称预构建,文件位于./prebuild.ts)需要执行构建命令前,运行在node运行时,而node运行时不支持解析ts文件类型。那很好办啊,通过ts-node去执行这个预购建脚本不就可以了。当我兴冲冲的修改package.json中的script里的prebuild为npx ts-node ./prebuild.ts,直接就报错了,不支持import。查了下ts-node文档,加了个--esm的执行参数,这下总行了吧?嘿嘿,没这么简单。

最终效果如图所示

继续阅读 »

我目前使用的是参考官方vue3+ts+vite的cli模板示例,去除暂时不涉及到的平台的npm依赖,这样就能够使用eslint+prettier等工具链以及vscode实现更贴近传统web开发的开发体验。整体运行良好,即使需要用插件库也可以通过下载解压对应包到本地实现,唯二有个两问题一直不能很好的解决,其一就是路由跳转的类型校验。

uniapp沿用和对齐微信小程序的pages.json来实现页面路由的控制,hbuilderx可以实现一部分跳转的路由提示,但还是不够完善,且不能对无效路由做错误提示。经过几次尝试,最后终于实现了一个完美的解决方案。

最开始的时候是想通过自己封装下路由,然后import pages.json中的数据结构,去实现路由的类型校验。但是因为ts对于json的解析是直接解析成了string这个比较宽泛的类别,且无法通过类型推断(as const)去实现,详见https://github.com/microsoft/TypeScript/issues/32063

既然无法通过json实现类型推断,那么可以转换下思路,通过ts去配置pages,但是uniapp不兼容这种方案。那么可以再进一步,通过ts配置pages,在执行uniapp的构建命令前根据这个pages.ts去生成pages.json。

理想很丰满,现实很骨感,这个思路的方向是对的,然而在实现pages.ts输出到pages.json出现了好多问题。迎面而来的是:这段逻辑(下称预构建,文件位于./prebuild.ts)需要执行构建命令前,运行在node运行时,而node运行时不支持解析ts文件类型。那很好办啊,通过ts-node去执行这个预购建脚本不就可以了。当我兴冲冲的修改package.json中的script里的prebuild为npx ts-node ./prebuild.ts,直接就报错了,不支持import。查了下ts-node文档,加了个--esm的执行参数,这下总行了吧?嘿嘿,没这么简单。

最终效果如图所示

收起阅读 »

软键盘顶起 fixed 定位的解决方法

uniapp 弹出软键盘

我个人的解决方法
在 app.vue 页面用 uni.getWindowInfo() 方法获取手机长度,并且传到 vuex 里

this.$store.commit("SET_WINDOWHEIGHT",uni.getWindowInfo().windowHeight)

将 position: fixed;定位改为 position: absolute; 然后给 页面的第一个 view 设置 最小高度,并加上 position: relative;

<view style="position: relative;" :style="windowHeight?'min-height:'+windowHeight+'px':''">  
</view>
继续阅读 »

我个人的解决方法
在 app.vue 页面用 uni.getWindowInfo() 方法获取手机长度,并且传到 vuex 里

this.$store.commit("SET_WINDOWHEIGHT",uni.getWindowInfo().windowHeight)

将 position: fixed;定位改为 position: absolute; 然后给 页面的第一个 view 设置 最小高度,并加上 position: relative;

<view style="position: relative;" :style="windowHeight?'min-height:'+windowHeight+'px':''">  
</view>
收起阅读 »

上拉加载的bug ,结构中渲染内容稍多点,上拉至一定的页码,视图不更新

上拉加载

上拉加载的bug ,结构中渲染内容稍多点,上拉至一定的页码,视图就不更新了,如图一所示展示到950条,再进行上拉,视图就不更新。dataList里面的数据已经改变了。
使用第三方上拉组件或者onReachBottom都不行

上拉加载的bug ,结构中渲染内容稍多点,上拉至一定的页码,视图就不更新了,如图一所示展示到950条,再进行上拉,视图就不更新。dataList里面的数据已经改变了。
使用第三方上拉组件或者onReachBottom都不行

uni-ai,帮您快速引入ai能力;uni-cms,内容管理全套方案;uni安全专题、uni金融级实人认证;uts插件支持计费销售

公告
继续阅读 »
收起阅读 »

关于height,padding,margin的百分值的问题

HTML5 css

width的百分值是由父元素的width决定的,默认auto,块级元素为100%,这里要考虑bfc的影响,块级元素为bfc后,默认auto。
height的百分值是由父元素的height决定的,如果父元素没有设置固定值或是父元素为100%及其祖父元素没有固定值,当前元素设height为百分比时,可能无效。
padding的百分值是由父元素的宽决定的,
margin的百分值是由父元素的宽决定的,
如 父元素的宽为290px,padding-left:20% ->padding-left:58px;

注意;BFC在布居中的影响!!!

flex布局时,元素会以每行最高元素的为准,前提是你的元素没有设置高度时,如设了高度,以自身高度为准。

可以去尝试测试一下,有用的话,记得点个赞哟!!!

继续阅读 »

width的百分值是由父元素的width决定的,默认auto,块级元素为100%,这里要考虑bfc的影响,块级元素为bfc后,默认auto。
height的百分值是由父元素的height决定的,如果父元素没有设置固定值或是父元素为100%及其祖父元素没有固定值,当前元素设height为百分比时,可能无效。
padding的百分值是由父元素的宽决定的,
margin的百分值是由父元素的宽决定的,
如 父元素的宽为290px,padding-left:20% ->padding-left:58px;

注意;BFC在布居中的影响!!!

flex布局时,元素会以每行最高元素的为准,前提是你的元素没有设置高度时,如设了高度,以自身高度为准。

可以去尝试测试一下,有用的话,记得点个赞哟!!!

收起阅读 »

瀑布流怎么实现?怎么自己手写瀑布流

实在忍受不了之前写的瀑布流,太难用了。自己写了一套。
插件分享:https://ext.dcloud.net.cn/plugin?id=9634
其实,很简单。
1,分两列,有两个数字分别记录高度
2,每一个卡片是固定高的。这个高度是用于计算,应该在左边还是右边的
3,第一个固定设置成长的,第二个固定设置成短的,出来效果一定是瀑布流
4,防止记录高度的数字太大,每次计算完,归零一个,另一个是两数之差。
自己试一下吧!
两列能写,多少列也都能写,都是一样的

继续阅读 »

实在忍受不了之前写的瀑布流,太难用了。自己写了一套。
插件分享:https://ext.dcloud.net.cn/plugin?id=9634
其实,很简单。
1,分两列,有两个数字分别记录高度
2,每一个卡片是固定高的。这个高度是用于计算,应该在左边还是右边的
3,第一个固定设置成长的,第二个固定设置成短的,出来效果一定是瀑布流
4,防止记录高度的数字太大,每次计算完,归零一个,另一个是两数之差。
自己试一下吧!
两列能写,多少列也都能写,都是一样的

收起阅读 »

vue3 steup和 renderjs 交互问题

vue3
<div id="demoSvag" :prop="svgaPath" :change:prop="svgaModule.onChange" style="width: 500rpx;height: 580rpx;"></div>

本以为这样就可以通过修改svgaPath 就可以触发svgaModule中的onChange方法 结果是没反应,触发不了

经过仔细对比发现 绑定的标签用的是 div 然后试了下换成 view就可以了

小问题,找了一上午

继续阅读 »
<div id="demoSvag" :prop="svgaPath" :change:prop="svgaModule.onChange" style="width: 500rpx;height: 580rpx;"></div>

本以为这样就可以通过修改svgaPath 就可以触发svgaModule中的onChange方法 结果是没反应,触发不了

经过仔细对比发现 绑定的标签用的是 div 然后试了下换成 view就可以了

小问题,找了一上午

收起阅读 »

vue-router RangeError: Maximum call stack size exceeded

Vue

操作路由时出现RangeError: Maximum call stack size exceeded,
一般是出现路由死循环。要检查路由钩子函数里的next是否使用得当,如有判断,要看判断条件是否有漏,如next("/login"),要判断to.path不为login的路径才执行next("/login"),否则会出现路由死循环

/login - > /login ->/login - > /login

继续阅读 »

操作路由时出现RangeError: Maximum call stack size exceeded,
一般是出现路由死循环。要检查路由钩子函数里的next是否使用得当,如有判断,要看判断条件是否有漏,如next("/login"),要判断to.path不为login的路径才执行next("/login"),否则会出现路由死循环

/login - > /login ->/login - > /login

收起阅读 »

vue页面的web-view通讯, 如何在APP 和网页中调用html方法

这个是html通知uni-app方法  
// 待触发 `UniAppJSBridgeReady` 事件后,即可调用 uni 的 API。  
document.addEventListener('UniAppJSBridgeReady', function() {  
    uni.postMessage({  
        data: {  
            action: 'load'  
        }  
    })  
})
<template>  
    <web-view id="iframe" ref="webview" @message="onPostMessage"></web-view>  
</template>  

<script>  
let wv = null // html页面实例  
export default {  
    data() {  
        return {  
        };  
    },  
    onUnload() {  
        // 退出页面卸载监听  
        // #ifdef H5  
        window.removeEventListener('message', this.h5PostMessage, false);  
        // #endif  
    },  
    onLoad() {  
        // 监听html页面传递过来的消息  
        // #ifdef H5  
        window.addEventListener('message', this.h5PostMessage, false);  
        // #endif  
    },  
        onReady() {  
        // 获取html页面实例  
        // #ifdef APP-PLUS  
        const currentWebview = this.$scope.$getAppWebview();    
        setTimeout(() => {  
            wv = currentWebview.children()[0]  
        },100)  
        // #endif  
    },  
    methods: {  
        h5PostMessage(event) {  
                        // 非postMessage事件过滤掉   
            if (event.data.data.name != 'postMessage') return;  
                        this.onPostMessage({  
                detail: {  
                    data: [event.data.data.arg]  
                }  
            });  
        },  
                onPostMessage(event) {  
            // html发过来的数据  

        },  
        evalJsHeaderClass(info) {  
            // 注意这里是evalJS  不是 nvue的 evalJs  
            // #ifdef APP-PLUS  
            wv.evalJS(`window.html里面的方法(${JSON.stringify(info)})`)  
            // #endif  
            // #ifdef H5  
            if (this.$refs.webview.iframe) {  
                const _iframe = this.$refs.webview.iframe.contentWindow;  
                _iframe.html里面的方法(info);  
            }  
            // #endif  
        }  
    }  
};  
</script>  

<style lang="scss">  
.flex-1 {  
    height: 100%;  
}  
</style>  
继续阅读 »
这个是html通知uni-app方法  
// 待触发 `UniAppJSBridgeReady` 事件后,即可调用 uni 的 API。  
document.addEventListener('UniAppJSBridgeReady', function() {  
    uni.postMessage({  
        data: {  
            action: 'load'  
        }  
    })  
})
<template>  
    <web-view id="iframe" ref="webview" @message="onPostMessage"></web-view>  
</template>  

<script>  
let wv = null // html页面实例  
export default {  
    data() {  
        return {  
        };  
    },  
    onUnload() {  
        // 退出页面卸载监听  
        // #ifdef H5  
        window.removeEventListener('message', this.h5PostMessage, false);  
        // #endif  
    },  
    onLoad() {  
        // 监听html页面传递过来的消息  
        // #ifdef H5  
        window.addEventListener('message', this.h5PostMessage, false);  
        // #endif  
    },  
        onReady() {  
        // 获取html页面实例  
        // #ifdef APP-PLUS  
        const currentWebview = this.$scope.$getAppWebview();    
        setTimeout(() => {  
            wv = currentWebview.children()[0]  
        },100)  
        // #endif  
    },  
    methods: {  
        h5PostMessage(event) {  
                        // 非postMessage事件过滤掉   
            if (event.data.data.name != 'postMessage') return;  
                        this.onPostMessage({  
                detail: {  
                    data: [event.data.data.arg]  
                }  
            });  
        },  
                onPostMessage(event) {  
            // html发过来的数据  

        },  
        evalJsHeaderClass(info) {  
            // 注意这里是evalJS  不是 nvue的 evalJs  
            // #ifdef APP-PLUS  
            wv.evalJS(`window.html里面的方法(${JSON.stringify(info)})`)  
            // #endif  
            // #ifdef H5  
            if (this.$refs.webview.iframe) {  
                const _iframe = this.$refs.webview.iframe.contentWindow;  
                _iframe.html里面的方法(info);  
            }  
            // #endif  
        }  
    }  
};  
</script>  

<style lang="scss">  
.flex-1 {  
    height: 100%;  
}  
</style>  
收起阅读 »

Module Error 模块错误

view
<template>  

        <view>1</view>  
        <view>2</view>  

</template>  

<script>  
</script>  

<style>  
</style>

该文档编译后出现Module Error 模块错误提示

11:14:32.435 正在编译中...  
11:14:33.114  INFO  Starting development server...  
11:14:37.884 Module Error (from ./node_modules/@dcloudio/vue-cli-plugin-uni/packages/vue-loader/lib/loaders/templateLoader.js):  
11:14:37.884 (Emitted value instead of an instance of Error)   
11:14:37.888   Errors compiling template:  
11:14:37.888   Component template should contain exactly one root element. If you are using v-if on multiple elements, use v-else-if to chain them instead.  
11:14:37.893   1  |    
11:14:37.893   2  |    
11:14:37.900   3  |  <view>1</view>  
11:14:37.900      |                   
11:14:37.903   4  |  <view>2</view>  
11:14:37.907      |  ^^^^^^^^^^^^^^  
11:14:37.911   5  |    
11:14:37.913      |    

需要在1和2两个模块外再套一层view

<template>  
        <view>  
        <view>1</view>  
        <view>2</view>  
        </view>  
</template>  

<script>  
</script>  

<style>  
</style>

也就是说在template之间只能有一个主view,
不能有两个同时出现并列的view,
如果有就只能作为子view嵌套进主view中去。

继续阅读 »
<template>  

        <view>1</view>  
        <view>2</view>  

</template>  

<script>  
</script>  

<style>  
</style>

该文档编译后出现Module Error 模块错误提示

11:14:32.435 正在编译中...  
11:14:33.114  INFO  Starting development server...  
11:14:37.884 Module Error (from ./node_modules/@dcloudio/vue-cli-plugin-uni/packages/vue-loader/lib/loaders/templateLoader.js):  
11:14:37.884 (Emitted value instead of an instance of Error)   
11:14:37.888   Errors compiling template:  
11:14:37.888   Component template should contain exactly one root element. If you are using v-if on multiple elements, use v-else-if to chain them instead.  
11:14:37.893   1  |    
11:14:37.893   2  |    
11:14:37.900   3  |  <view>1</view>  
11:14:37.900      |                   
11:14:37.903   4  |  <view>2</view>  
11:14:37.907      |  ^^^^^^^^^^^^^^  
11:14:37.911   5  |    
11:14:37.913      |    

需要在1和2两个模块外再套一层view

<template>  
        <view>  
        <view>1</view>  
        <view>2</view>  
        </view>  
</template>  

<script>  
</script>  

<style>  
</style>

也就是说在template之间只能有一个主view,
不能有两个同时出现并列的view,
如果有就只能作为子view嵌套进主view中去。

收起阅读 »