
uniapp设置强制竖屏wgt包强制竖屏uniapp锁定屏幕竖直方向
分为三步
- 第一步
uniapp 根目录下pages.json 文件中追加下面四项
"globalStyle": {
"pageOrientation": "portrait", //横屏配置,全局屏幕旋转设置(仅 APP/微信/QQ小程序),支持 auto / portrait / landscape
"rpxCalcMaxDeviceWidth": 960,
"rpxCalcBaseDeviceWidth": 375,
"rpxCalcIncludeWidth": 750
} - 第二步
uniapp 根目录下mainfest.json文件中追加如下配置
distribute" : {
"orientation" : ["portrait-primary" ] //重力感应、横竖屏配置
} - 第三步
在你想强制横竖屏的页面的vue文件中的 onLoad 或者onShow的生命周期里面 加上如下代码即可
//#ifdef APP-PLUS
plus.screen.lockOrientation('portrait-primary');
//#endif
横竖屏切换都可参照此篇文章 已本人亲自尝试,如有疑问者 可下方留言 会帮忙解答
分为三步
- 第一步
uniapp 根目录下pages.json 文件中追加下面四项
"globalStyle": {
"pageOrientation": "portrait", //横屏配置,全局屏幕旋转设置(仅 APP/微信/QQ小程序),支持 auto / portrait / landscape
"rpxCalcMaxDeviceWidth": 960,
"rpxCalcBaseDeviceWidth": 375,
"rpxCalcIncludeWidth": 750
} - 第二步
uniapp 根目录下mainfest.json文件中追加如下配置
distribute" : {
"orientation" : ["portrait-primary" ] //重力感应、横竖屏配置
} - 第三步
在你想强制横竖屏的页面的vue文件中的 onLoad 或者onShow的生命周期里面 加上如下代码即可
//#ifdef APP-PLUS
plus.screen.lockOrientation('portrait-primary');
//#endif
横竖屏切换都可参照此篇文章 已本人亲自尝试,如有疑问者 可下方留言 会帮忙解答
收起阅读 »
Biaofun建信小程序开发工具链原理浅析
@jump-mp/cli 的安装和使用方法详见建信小程序开发文档。
在终端运行
$ jump -h
可以看到 @jump-mp/cli 中提供如下功能:
Usage: jump <command> [options]
Options:
-v, --version output the version number
-h, --help display help for command
Commands:
init initialize template for jump project
build [options] build project to be used in android or ios
update update project dependencies to the latest version
add [options] <source-name> add npm source for miniproject
construct construct installed npm source for miniproject
help [command] display help for command
init:初始化方法,用于初始化小程序项目和页面、组件;
build:用于对建信小程序进行编译打包;
update:用于更新建信小程序使用的依赖版本;
add:用于添加小程序依赖;
construct:用于构建小程序添加的依赖。
脚手架原理
在上一节中,已经介绍了 @jump-mp/cli 的基本功能。本节将对脚手架 @jump-mp/cli 的整体架构和技术选型进行介绍。
01
现有脚手架技术分析
目前较常用的前端开发脚手架工具有 yoeman、vue-cli 等。
yeoman 搭建项目需要提供 yoeman-generator。yoeman-generator 本质上就是有 i 个具备完整文件结构的项目样板,用户需要手动地把这些 generator 下载到本地,然后 yoeman 就会根据这些 generator 自动生成各种不同的项目。
vue-cli 提供了相当丰富的选项和设定功能,但是其本质也是从远程仓库把不同的模版拉取到本地,而并非是“本地生成“的黑科技。
综上,目前脚手架的思路大都是建立不同的样板项目,然后脚手架根据用户指令引用样板项目生成实际项目。样板项目可以内置在脚手架中,也可以部署在远程仓库。
02
技术选型及架构
为了更好地实现模版定制和功能开发,大前端团队自研了建信小程序脚手架 @jump-mp/cli。脚手架主要使用了以下技术:
node.js:整个脚手架工具的根本组成部分。
commander: 用于组织和处理命令行的输入。
webpack:用于对一些需要编译的文件进行处理。
脚手架的整体架构如下图:
在创建小程序、页面和组件时,小程序的项目、页面和组件的模版(template)都存放在依赖 jump-mp/cli-template 中。每当用户需要创建时,就通过 cli 的命令向 jump-mp/cli-template 中拉取相应的模版并下载到本地。
对于编译、构建等功能,会在后面的小节进行介绍。
最终整个 @jump-mp/cli 的脚手架文件结构如下。
├── bin
│ └── index.js
├── command
│ ├── add.js
│ ├── build.js
│ ├── create.js
│ ├── translate.js
│ └── update.js
├── node_modules
│ └── @jump-mp
│ ├── build
│ └── cli-template
│ ├── component
│ ├── page
│ └── project
└── package.json
其中 bin/index.s为入口文件,主要用 commander 来构建命令行。commander 的工作流程如下:
编译器原理
在完成小程序的开发后,需要在项目根目录下运行 jump build [option] 来对小程序进行编译打包。下面将介绍建信小程序打包过程中的编译原理。
01
小程序引擎
在《初识建信小程序引擎》一文中我们了解到,为了提升小程序的运行性能、用户体验,建信小程序采用了双线程模式,将运行环境分为视图层(view 层)和逻辑层(service 层)。其中视图层负责页面展示,逻辑层负责小程序业务逻辑。视图层和逻辑层分别由 2 个线程管理:
视图层的界面使用了 WebView 进行渲染,视图层使用 Vuejs 作为 MVVM 框架;
逻辑层采用 JsCore 线程运行 JavaScript 脚本。
同时,视图层线程和逻辑层线程通信会经由建信客户端(Native 层)做中转,逻辑层发送网络请求也经由 Native 层转发,Native 层也会渲染一些原生的组件、被小程序调用一些原生的 API。
综上,编译器的主要功能是将小程序代码进行编译,将 view 层、service 层、native 层三个部分各自需要的代码进行提取、转换、整合,最终打包成一个可以在建信客户端运行的小程序。
02
技术选型
编译器主要使用了以下技术:
node.js:整个脚手架工具的根本组成部分。
gulp:基于流的自动化构建工具。
babel相关:用于构建 js 代码的 ast 树、修改 js 代码、编译 js 代码。
vue-template-compiler:用于构建 html 代码的 ast 树,修改 html 代码、编译 html 代码。
postcss:用于修改、编译 css 代码。
webpack:用于对一些需要编译的文件进行处理。
03
编译器原理
编译器在工作的过程中,会经历预处理、编译、打包三个步骤,具体流程如下:
下面将详细描述编译原理和流程。
(1)mxml—>使用 vue 框架的 html
对于页面/组件的 mxml 页面,编译器做了如下处理:
首先,mxml 会被解析为一颗 ast 抽象语法树
然后,编译器会遍历该 ast 语法树,将组件名转为小程序内置组件名(例:button->mp-button),将建信小程序语法标签转为 vue 语法标签(例:mp:if->v-if)。
最后,遍历该 ast 抽象语法树,将 ast 转为使用 vue 框架的 html 代码。
(2)mcss—>css
将 mcss 转为 css 主要做了设备视图分辨率适配,将 rpx 单位转为 vw。
(3)使用 vue 框架的 html—>使用 vue 框架的 page.view.js
在生成了 html 中间态文件“使用 vue 框架的 html” 后,还需要生成一个符合 vue 框架要求的 js 文件,然后将其组合到一个 html 文件(及 page.html)中,该文件才可在使用了 vue 引擎的视图层中被加载,因此我们需要一个这样的 html 文件。举例说明:
jump 小程序:
mxml
<view>
<view>{{title}}</view>
<button bindtap="clickMe">请点击换标题</button>
</view>
js
Page({
data: {
title: 'Hello World',
},
//事件处理函数
clickMe: function() {
this.setData({
title: '你好,世界'
})
}
})
那么转换之后的 vue 页面应该是:
<template>
<mp-view>
<mp-view>{{title}}</mp-view>
<mp-button @click="clickMe">请点击换标题</mp-button>
<mp-view>
<template>
<script>
export default {
data(){
return {
title: '',
}
}
}
</script>
这里 data 中的变量名不是通过解析 page.js 得到的,因为开发者在编写 page.js 时是没有要求固定格式的,因此无法通过抽象代码树解析的方式拿到 data 的参数,所以这里 data 的变量名是通过解析 html 表达式拿到的。
而没有将 data 中的数据值和 method 方法写到 html 页面中,是因为这部分应由 service 逻辑层处理,view 层只需声明变量名即可。
最终再通过 vue 生成的 html 页面应为:
<html>
<head>......</head>
<body>
......
<script>
new Vue({
data() {
return {
title:""
}
},
el: "#app",
template:"<template><mp-view><mp-view>{{title}}</mp-view><mp-button @click="clickMe">请点击换标题</mp-button> <mp-view><template>"
});
</script>
</body>
</html>
如要生成上述页面,首先我们需要拿到data中的变量名,使用的方法是,通过解析 html 中的表达式来获得变量名。
然后则是构建 html 页面中的 js 代码,这里使用 babel 去构建一个 js 的 ast 抽象语法树,然后向树中插入 data 和 template 的参数和值。
由于考虑到随着页面功能的增多以及版本的迭代,直接构建目标态代码,在未来版本发生迭代时很可能会导致编译逻辑会跟随修改。为了解决这一问题,我们需要区分出目标态代码的不变部分和可变部分。把不变部分抽象为源对象,把可变部分交由 runtime 运行时框架处理。这样只需要在 rumtime 层做版本迭代而不需要编译器修改。
为了提高加载速度,我们在编译阶段做了预处理,把原本在运行时处理的渲染模版提前展开为真实的虚拟节点树。
所以本步骤整体的工作流程如下图:
最终生成的 page.view.js 应为:
let app = window.$$makeVueComponent({
data() {
return {
title: ""
};
},
el: "#app",
render: function anonymous() {
with(this){return _c('mp-view',[_c('mp-view',[_c('mp-view',[_v(_s(title))]),_v(" "),_c('mp-button',{on:{"click":function($event){return eventHandlerProxy('clickMe',$event)}}},[_v("请点击换标题")])],1)],1)}
},
staticRenderFns: []
});
new Vue(app);
(4)页面(page)中引入的组件(component)的处理
由于视图 view 层在加载页面时只会去加载该页面的 html,因此需要在编译页面时将页面中引入的组件(component)也编译进 html 中。这里的编译流程如下:
编译器会先读取所编译的 page 的 json 文件,如果 json 文件中引入了组件,则将编译后的组件的 js 加入到 page 的 html 中。然后再去读取改组件的 json 文件,查看改组件是否引入了其他组件,一直递归循环,直至所有组件都被编译进 html 文件为止。对于每个页面重复引入的组件,则只编入一次。
(5)page.js 的编译
在处理需要在 service 逻辑层运行的 page.js 时,我们不会去改变文件的代码,只是对 page.js 用 webpack 做编译打包,然后汇总到 app-service.js 文件中。
构建 npm 依赖
建信小程序支持引入第三方 npm 依赖。这里不再对 npm 的功能进行介绍,可以参考官方 npm 文档。
01
使用方法
建信小程序引入 npm 依赖,需要添加依赖和构建依赖两个步骤。
其中,构建依赖的目的是,将安装在 node_modules 下的依赖进行编译构建,然后生成到项目根目录下的 npm_miniprogram 文件夹下,以供小程序在开发过程中进行引入。
02
构建原理
在使用 npm 依赖时需要构建依赖,是因为在小程序编译时,无法在未指定路径的情况下将 require 的 node_modules 下的依赖编译进去,所以需要构建这个步骤,将依赖进行预编译,然后统一到一个目录下。
npm 依赖的构建原理如下图所示:
首先会读取项目根目录下的package.json, 如果 devDependencies/dependencies 不为空,则小程序中有使用 npm 依赖,需要构建。
在 node_modules 中找到小程序引入的依赖,查看该依赖是否指明小程序的引入入口(miniprogram_dist 目录),如果有则直接将其复制到 miniprogram_npm 路径下,如果没有则使用 webpack 由 main 入口进行编译,编译结果保存到 miniprogram_npm 路径。
对构建完成的 npm 依赖 重复第一步的步骤,直到所有依赖及依赖的依赖构建完成。
文章来源:Biaofun标梵互动(https://www.biaofun.com/)
@jump-mp/cli 的安装和使用方法详见建信小程序开发文档。
在终端运行
$ jump -h
可以看到 @jump-mp/cli 中提供如下功能:
Usage: jump <command> [options]
Options:
-v, --version output the version number
-h, --help display help for command
Commands:
init initialize template for jump project
build [options] build project to be used in android or ios
update update project dependencies to the latest version
add [options] <source-name> add npm source for miniproject
construct construct installed npm source for miniproject
help [command] display help for command
init:初始化方法,用于初始化小程序项目和页面、组件;
build:用于对建信小程序进行编译打包;
update:用于更新建信小程序使用的依赖版本;
add:用于添加小程序依赖;
construct:用于构建小程序添加的依赖。
脚手架原理
在上一节中,已经介绍了 @jump-mp/cli 的基本功能。本节将对脚手架 @jump-mp/cli 的整体架构和技术选型进行介绍。
01
现有脚手架技术分析
目前较常用的前端开发脚手架工具有 yoeman、vue-cli 等。
yeoman 搭建项目需要提供 yoeman-generator。yoeman-generator 本质上就是有 i 个具备完整文件结构的项目样板,用户需要手动地把这些 generator 下载到本地,然后 yoeman 就会根据这些 generator 自动生成各种不同的项目。
vue-cli 提供了相当丰富的选项和设定功能,但是其本质也是从远程仓库把不同的模版拉取到本地,而并非是“本地生成“的黑科技。
综上,目前脚手架的思路大都是建立不同的样板项目,然后脚手架根据用户指令引用样板项目生成实际项目。样板项目可以内置在脚手架中,也可以部署在远程仓库。
02
技术选型及架构
为了更好地实现模版定制和功能开发,大前端团队自研了建信小程序脚手架 @jump-mp/cli。脚手架主要使用了以下技术:
node.js:整个脚手架工具的根本组成部分。
commander: 用于组织和处理命令行的输入。
webpack:用于对一些需要编译的文件进行处理。
脚手架的整体架构如下图:
在创建小程序、页面和组件时,小程序的项目、页面和组件的模版(template)都存放在依赖 jump-mp/cli-template 中。每当用户需要创建时,就通过 cli 的命令向 jump-mp/cli-template 中拉取相应的模版并下载到本地。
对于编译、构建等功能,会在后面的小节进行介绍。
最终整个 @jump-mp/cli 的脚手架文件结构如下。
├── bin
│ └── index.js
├── command
│ ├── add.js
│ ├── build.js
│ ├── create.js
│ ├── translate.js
│ └── update.js
├── node_modules
│ └── @jump-mp
│ ├── build
│ └── cli-template
│ ├── component
│ ├── page
│ └── project
└── package.json
其中 bin/index.s为入口文件,主要用 commander 来构建命令行。commander 的工作流程如下:
编译器原理
在完成小程序的开发后,需要在项目根目录下运行 jump build [option] 来对小程序进行编译打包。下面将介绍建信小程序打包过程中的编译原理。
01
小程序引擎
在《初识建信小程序引擎》一文中我们了解到,为了提升小程序的运行性能、用户体验,建信小程序采用了双线程模式,将运行环境分为视图层(view 层)和逻辑层(service 层)。其中视图层负责页面展示,逻辑层负责小程序业务逻辑。视图层和逻辑层分别由 2 个线程管理:
视图层的界面使用了 WebView 进行渲染,视图层使用 Vuejs 作为 MVVM 框架;
逻辑层采用 JsCore 线程运行 JavaScript 脚本。
同时,视图层线程和逻辑层线程通信会经由建信客户端(Native 层)做中转,逻辑层发送网络请求也经由 Native 层转发,Native 层也会渲染一些原生的组件、被小程序调用一些原生的 API。
综上,编译器的主要功能是将小程序代码进行编译,将 view 层、service 层、native 层三个部分各自需要的代码进行提取、转换、整合,最终打包成一个可以在建信客户端运行的小程序。
02
技术选型
编译器主要使用了以下技术:
node.js:整个脚手架工具的根本组成部分。
gulp:基于流的自动化构建工具。
babel相关:用于构建 js 代码的 ast 树、修改 js 代码、编译 js 代码。
vue-template-compiler:用于构建 html 代码的 ast 树,修改 html 代码、编译 html 代码。
postcss:用于修改、编译 css 代码。
webpack:用于对一些需要编译的文件进行处理。
03
编译器原理
编译器在工作的过程中,会经历预处理、编译、打包三个步骤,具体流程如下:
下面将详细描述编译原理和流程。
(1)mxml—>使用 vue 框架的 html
对于页面/组件的 mxml 页面,编译器做了如下处理:
首先,mxml 会被解析为一颗 ast 抽象语法树
然后,编译器会遍历该 ast 语法树,将组件名转为小程序内置组件名(例:button->mp-button),将建信小程序语法标签转为 vue 语法标签(例:mp:if->v-if)。
最后,遍历该 ast 抽象语法树,将 ast 转为使用 vue 框架的 html 代码。
(2)mcss—>css
将 mcss 转为 css 主要做了设备视图分辨率适配,将 rpx 单位转为 vw。
(3)使用 vue 框架的 html—>使用 vue 框架的 page.view.js
在生成了 html 中间态文件“使用 vue 框架的 html” 后,还需要生成一个符合 vue 框架要求的 js 文件,然后将其组合到一个 html 文件(及 page.html)中,该文件才可在使用了 vue 引擎的视图层中被加载,因此我们需要一个这样的 html 文件。举例说明:
jump 小程序:
mxml
<view>
<view>{{title}}</view>
<button bindtap="clickMe">请点击换标题</button>
</view>
js
Page({
data: {
title: 'Hello World',
},
//事件处理函数
clickMe: function() {
this.setData({
title: '你好,世界'
})
}
})
那么转换之后的 vue 页面应该是:
<template>
<mp-view>
<mp-view>{{title}}</mp-view>
<mp-button @click="clickMe">请点击换标题</mp-button>
<mp-view>
<template>
<script>
export default {
data(){
return {
title: '',
}
}
}
</script>
这里 data 中的变量名不是通过解析 page.js 得到的,因为开发者在编写 page.js 时是没有要求固定格式的,因此无法通过抽象代码树解析的方式拿到 data 的参数,所以这里 data 的变量名是通过解析 html 表达式拿到的。
而没有将 data 中的数据值和 method 方法写到 html 页面中,是因为这部分应由 service 逻辑层处理,view 层只需声明变量名即可。
最终再通过 vue 生成的 html 页面应为:
<html>
<head>......</head>
<body>
......
<script>
new Vue({
data() {
return {
title:""
}
},
el: "#app",
template:"<template><mp-view><mp-view>{{title}}</mp-view><mp-button @click="clickMe">请点击换标题</mp-button> <mp-view><template>"
});
</script>
</body>
</html>
如要生成上述页面,首先我们需要拿到data中的变量名,使用的方法是,通过解析 html 中的表达式来获得变量名。
然后则是构建 html 页面中的 js 代码,这里使用 babel 去构建一个 js 的 ast 抽象语法树,然后向树中插入 data 和 template 的参数和值。
由于考虑到随着页面功能的增多以及版本的迭代,直接构建目标态代码,在未来版本发生迭代时很可能会导致编译逻辑会跟随修改。为了解决这一问题,我们需要区分出目标态代码的不变部分和可变部分。把不变部分抽象为源对象,把可变部分交由 runtime 运行时框架处理。这样只需要在 rumtime 层做版本迭代而不需要编译器修改。
为了提高加载速度,我们在编译阶段做了预处理,把原本在运行时处理的渲染模版提前展开为真实的虚拟节点树。
所以本步骤整体的工作流程如下图:
最终生成的 page.view.js 应为:
let app = window.$$makeVueComponent({
data() {
return {
title: ""
};
},
el: "#app",
render: function anonymous() {
with(this){return _c('mp-view',[_c('mp-view',[_c('mp-view',[_v(_s(title))]),_v(" "),_c('mp-button',{on:{"click":function($event){return eventHandlerProxy('clickMe',$event)}}},[_v("请点击换标题")])],1)],1)}
},
staticRenderFns: []
});
new Vue(app);
(4)页面(page)中引入的组件(component)的处理
由于视图 view 层在加载页面时只会去加载该页面的 html,因此需要在编译页面时将页面中引入的组件(component)也编译进 html 中。这里的编译流程如下:
编译器会先读取所编译的 page 的 json 文件,如果 json 文件中引入了组件,则将编译后的组件的 js 加入到 page 的 html 中。然后再去读取改组件的 json 文件,查看改组件是否引入了其他组件,一直递归循环,直至所有组件都被编译进 html 文件为止。对于每个页面重复引入的组件,则只编入一次。
(5)page.js 的编译
在处理需要在 service 逻辑层运行的 page.js 时,我们不会去改变文件的代码,只是对 page.js 用 webpack 做编译打包,然后汇总到 app-service.js 文件中。
构建 npm 依赖
建信小程序支持引入第三方 npm 依赖。这里不再对 npm 的功能进行介绍,可以参考官方 npm 文档。
01
使用方法
建信小程序引入 npm 依赖,需要添加依赖和构建依赖两个步骤。
其中,构建依赖的目的是,将安装在 node_modules 下的依赖进行编译构建,然后生成到项目根目录下的 npm_miniprogram 文件夹下,以供小程序在开发过程中进行引入。
02
构建原理
在使用 npm 依赖时需要构建依赖,是因为在小程序编译时,无法在未指定路径的情况下将 require 的 node_modules 下的依赖编译进去,所以需要构建这个步骤,将依赖进行预编译,然后统一到一个目录下。
npm 依赖的构建原理如下图所示:
首先会读取项目根目录下的package.json, 如果 devDependencies/dependencies 不为空,则小程序中有使用 npm 依赖,需要构建。
在 node_modules 中找到小程序引入的依赖,查看该依赖是否指明小程序的引入入口(miniprogram_dist 目录),如果有则直接将其复制到 miniprogram_npm 路径下,如果没有则使用 webpack 由 main 入口进行编译,编译结果保存到 miniprogram_npm 路径。
对构建完成的 npm 依赖 重复第一步的步骤,直到所有依赖及依赖的依赖构建完成。
文章来源:Biaofun标梵互动(https://www.biaofun.com/)
收起阅读 »
app点击返回按钮出现提示框,确定的时候才返回
不加flag变量控制的话,点击返回,会死循环弹出提示框。
flag: true//是否弹出返回提示框
onBackPress() {
console.log("点击了返回");
if (this.flag) {
uni.showModal({
title: "温馨提示",
content: "是否确定退出?",
success: (res) => {
if (res.confirm) {
console.log("确定返回");
this.flag = false
uni.navigateBack({
delta: 1
})
return true
} else {
this.flag = true
console.log("取消");
return true
}
}
})
return true
}else{
return false
}
},
不加flag变量控制的话,点击返回,会死循环弹出提示框。
flag: true//是否弹出返回提示框
onBackPress() {
console.log("点击了返回");
if (this.flag) {
uni.showModal({
title: "温馨提示",
content: "是否确定退出?",
success: (res) => {
if (res.confirm) {
console.log("确定返回");
this.flag = false
uni.navigateBack({
delta: 1
})
return true
} else {
this.flag = true
console.log("取消");
return true
}
}
})
return true
}else{
return false
}
},
收起阅读 »

通告栏最简使用方案
多行上下轮播 使用swiper 代码如图
单行轮播可以使用css动画来实现
.notice {
position: absolute;
display: block;
white-space: nowrap;
padding-left: 100%;
animation: notice 10s 0s linear infinite both;
animation-play-state: paused;
/ 设置时间 /
animation-duration: 10s;
animation-play-state: running;
animation-delay: -3.51s;
}
@keyframes notice {
100% {
transform: translate3d(-100%, 0, 0);
}
}
多行上下轮播 使用swiper 代码如图
单行轮播可以使用css动画来实现
.notice {
position: absolute;
display: block;
white-space: nowrap;
padding-left: 100%;
animation: notice 10s 0s linear infinite both;
animation-play-state: paused;
/ 设置时间 /
animation-duration: 10s;
animation-play-state: running;
animation-delay: -3.51s;
}
@keyframes notice {
100% {
transform: translate3d(-100%, 0, 0);
}
}
收起阅读 »

判断进入登录页还是首页
页面初始化的时候,未登录跳转到登录页的话,会闪一下pages.json里的第一个首页。
而使用首页v-if来切换登录页面模板的话,tabbar又会闪一下。哪怕是在app.vue里写了uni.hideTabbar(),还是会闪。
最终只能在pages.json第一项搞个空白页,然后redirect到登录页了,看起来自然一点。
(我测试的环境是微信小程序,使用的hbuilderX是2.9.8)
页面初始化的时候,未登录跳转到登录页的话,会闪一下pages.json里的第一个首页。
而使用首页v-if来切换登录页面模板的话,tabbar又会闪一下。哪怕是在app.vue里写了uni.hideTabbar(),还是会闪。
最终只能在pages.json第一项搞个空白页,然后redirect到登录页了,看起来自然一点。
(我测试的环境是微信小程序,使用的hbuilderX是2.9.8)
收起阅读 »
vue nvue canvas video的吐槽
商品详情有个canvas画海报的功能,一开始没什么的
一天商品详情被要求支持短视频video,也没啥的
video在vue swiper中不能轮播,嗯开始有问题了
官方的建议是使用nvue
切换了一天,vue swiper video很完美
开心。。。。。
下班。。。。。
。。。。。。。
半路
测试说APP无法生成海报
卧槽,nvue不支持canvas
so,我现在又在电脑面前找解决方案
兄弟们
九九孩子
官方的NvueCanvasDemo不是我想要的
看来只能麻烦后台了
商品详情有个canvas画海报的功能,一开始没什么的
一天商品详情被要求支持短视频video,也没啥的
video在vue swiper中不能轮播,嗯开始有问题了
官方的建议是使用nvue
切换了一天,vue swiper video很完美
开心。。。。。
下班。。。。。
。。。。。。。
半路
测试说APP无法生成海报
卧槽,nvue不支持canvas
so,我现在又在电脑面前找解决方案
兄弟们
九九孩子
官方的NvueCanvasDemo不是我想要的
看来只能麻烦后台了
收起阅读 »
关于新版本canvasGetImageData报错的解决方法
蓝牙打印一直用到uni.canvasGetImageData生成画布,更新新版本后一直报错,现在使用uni.canvasPutImageData替代
uni.canvasPutImageData({
canvasId: 'prite_area_canvas',
x: 0,
y: 0,
width: canvasWidth,
height: canvasHeight,
data: command.getData(),
success: function(res) {
console.log('success')
command.setBitmap(res)
},
fail:function(){
console.log('fail')
},
complete: function() {
// command.setPrintAndFeedRow(3);
console.log('complete')
that.prepareSend(command.getData());
}
})
蓝牙打印一直用到uni.canvasGetImageData生成画布,更新新版本后一直报错,现在使用uni.canvasPutImageData替代
uni.canvasPutImageData({
canvasId: 'prite_area_canvas',
x: 0,
y: 0,
width: canvasWidth,
height: canvasHeight,
data: command.getData(),
success: function(res) {
console.log('success')
command.setBitmap(res)
},
fail:function(){
console.log('fail')
},
complete: function() {
// command.setPrintAndFeedRow(3);
console.log('complete')
that.prepareSend(command.getData());
}
})
收起阅读 »

Vue.js自定义垂直/水平滚动条组件|vue模拟滚动条
介绍
VScroll滚动条 基于vuejs2.x构建的美化XY轴滚动条组件。支持原生滚动条、鼠标移出是否隐藏滚动条、自定义滚动条尺寸、颜色及层级等功能。拥有漂亮且流畅的滚动体验!

参数配置
props: {
// 是否显示原生滚动条
native: Boolean,
// 是否自动隐藏滚动条
autohide: Boolean,
// 滚动条尺寸
size: { type: [Number, String], default: '' },
// 滚动条颜色
color: String,
// 滚动条层级
zIndex: null
},
快速引入
在main.js中引入组件。
import VScroll from './components/vscroll';
Vue.use(VScroll);
使用组件
<!-- 支持原生滚动条 -->
<v-scroll native>
<img src="https://cn.vuejs.org/images/logo.png" />
<p>这里是自定义内容。这里是自定义内容。这里是自定义内容。</p>
</v-scroll>
<!-- 参数配置 -->
<v-scroll autohide size="15" color="#00a1e0" zIndex="2021">
<img src="https://cn.vuejs.org/images/logo.png" />
<p>这里是自定义内容。这里是自定义内容。这里是自定义内容。</p>
</v-scroll>
实现过程
// vscroll模板
<template>
<div class="vui__scrollbar" ref="ref__box" @mouseenter="handleMouseEnter" @mouseleave="handleMouseLeave" v-resize="handleResize">
<div :class="['vscroll__wrap', {native: native}]" ref="ref__wrap" @scroll="handleScroll">
<div class="vscroll__view" v-resize="handleResize"><slot /></div>
</div>
<!-- //水平|垂直滚动条 -->
<div :class="['vscroll__bar vertical', {ishide: !isShow}]" @mousedown="handleClickTrack($event, 0)" :style="{'width': parseInt(size)>=0 ? parseInt(size)+'px' : '', 'z-index': parseInt(zIndex)>=0 ? parseInt(zIndex) : ''}">
<div class="vscroll__thumb" ref="ref__barY" :style="{'background': color, 'height': barHeight+'px'}" @mousedown="handleDragThumb($event, 0)"></div>
</div>
<div :class="['vscroll__bar horizontal', {ishide: !isShow}]" @mousedown="handleClickTrack($event, 1)" :style="{'height': parseInt(size)>=0 ? parseInt(size)+'px' : '', 'z-index': parseInt(zIndex)>=0 ? parseInt(zIndex) : ''}">
<div class="vscroll__thumb" ref="ref__barX" :style="{'background': color, 'width': barWidth+'px'}" @mousedown="handleDragThumb($event, 1)"></div>
</div>
</div>
</template>
/**
* @Desc VueJs虚拟滚动条组件VScroll
<script>
import domUtils from './utils/dom'
export default {
props: {
// 显示原生滚动条
native: Boolean,
// 自动隐藏滚动条
autohide: Boolean,
// 滚动条尺寸
size: { type: [Number, String], default: '' },
// 滚动条颜色
color: String,
// 滚动条层级
zIndex: null
},
data() {
return {
barWidth: 0, // 滚动条宽度
barHeight: 0, // 滚动条高度
ratioX: 1, // 滚动条水平偏移率
ratioY: 1, // 滚动条垂直偏移率
isTaped: false, // 鼠标光标是否按住滚动条
isHover: false, // 鼠标光标是否悬停在滚动区
isShow: !this.autohide, // 是否显示滚动条
}
},
mounted() {
this.$ref__box = this.$refs.ref__box
this.$ref__wrap = this.$refs.ref__wrap
this.$ref__barY = this.$refs.ref__barY
this.$ref__barX = this.$refs.ref__barX
this.$nextTick(this.updated)
},
// ...
methods: {
// 鼠标移入
handleMouseEnter() {
this.isHover = true
this.isShow = true
this.updated()
},
// 鼠标移出
handleMouseLeave() {
this.isHover = false
this.isShow = false
},
// 拖动滚动条
handleDragThumb(e, index) {
let _this = this
this.isTaped = true
let c = {}
domUtils.isIE() ? (e.returnValue = false, e.cancelBubble = true) : (e.stopPropagation(), e.preventDefault())
document.onselectstart = () => false
if(index == 0) {
c.dragY = true
c.clientY = e.clientY
}else {
c.dragX = true
c.clientX = e.clientX
}
domUtils.on(document, 'mousemove', function(evt) {
if(_this.isTaped) {
if(c.dragY) {
_this.$ref__wrap.scrollTop += (evt.clientY - c.clientY) * _this.ratioY
_this.$ref__barY.style.transform = `translateY(${_this.$ref__wrap.scrollTop / _this.ratioY}px)`
c.clientY = evt.clientY
}
if(c.dragX) {
_this.$ref__wrap.scrollLeft += (evt.clientX - c.clientX) * _this.ratioX
_this.$ref__barX.style.transform = `translateX(${_this.$ref__wrap.scrollLeft / _this.ratioX}px)`
c.clientX = evt.clientX
}
}
})
domUtils.on(document, 'mouseup', function() {
_this.isTaped = false
document.onmouseup = null;
document.onselectstart = null
})
},
// 滚动槽
handleClickTrack(e, index) {
console.log(index)
},
// 更新滚动
updated() {
if(this.native) return
// 垂直滚动条
if(this.$ref__wrap.scrollHeight > this.$ref__wrap.offsetHeight) {
this.barHeight = this.$ref__box.offsetHeight **2 / this.$ref__wrap.scrollHeight
this.ratioY = (this.$ref__wrap.scrollHeight - this.$ref__box.offsetHeight) / (this.$ref__box.offsetHeight - this.barHeight)
this.$ref__barY.style.transform = `translateY(${this.$ref__wrap.scrollTop / this.ratioY}px)`
}else {
this.barHeight = 0
this.$ref__barY.style.transform = ''
this.$ref__wrap.style.marginRight = ''
}
// 水平滚动条
...
},
handleResize() {
// 更新滚动条状态
},
// ...
}
}
</script>
vue中directives指令函数监听DOM变化。
// 监听元素/DOM尺寸变化
directives: {
'resize': {
bind: function(el, binding) {
let width = '', height = '';
function get() {
const elStyle = el.currentStyle ? el.currentStyle : document.defaultView.getComputedStyle(el, null);
if (width !== elStyle.width || height !== elStyle.height) {
binding.value({width, height});
}
width = elStyle.width;
height = elStyle.height;
}
el.__vueReize__ = setInterval(get, 16);
},
unbind: function(el) {
clearInterval(el.__vueReize__);
}
}
}
好了,今天就分享到这里。希望大家能喜欢哈!
基于vue.js网页弹窗组件|vue自定义对话框VLayer
链接:https://juejin.cn/post/6901103494971785223/
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
介绍
VScroll滚动条 基于vuejs2.x构建的美化XY轴滚动条组件。支持原生滚动条、鼠标移出是否隐藏滚动条、自定义滚动条尺寸、颜色及层级等功能。拥有漂亮且流畅的滚动体验!
参数配置
props: {
// 是否显示原生滚动条
native: Boolean,
// 是否自动隐藏滚动条
autohide: Boolean,
// 滚动条尺寸
size: { type: [Number, String], default: '' },
// 滚动条颜色
color: String,
// 滚动条层级
zIndex: null
},
快速引入
在main.js中引入组件。
import VScroll from './components/vscroll';
Vue.use(VScroll);
使用组件
<!-- 支持原生滚动条 -->
<v-scroll native>
<img src="https://cn.vuejs.org/images/logo.png" />
<p>这里是自定义内容。这里是自定义内容。这里是自定义内容。</p>
</v-scroll>
<!-- 参数配置 -->
<v-scroll autohide size="15" color="#00a1e0" zIndex="2021">
<img src="https://cn.vuejs.org/images/logo.png" />
<p>这里是自定义内容。这里是自定义内容。这里是自定义内容。</p>
</v-scroll>
实现过程
// vscroll模板
<template>
<div class="vui__scrollbar" ref="ref__box" @mouseenter="handleMouseEnter" @mouseleave="handleMouseLeave" v-resize="handleResize">
<div :class="['vscroll__wrap', {native: native}]" ref="ref__wrap" @scroll="handleScroll">
<div class="vscroll__view" v-resize="handleResize"><slot /></div>
</div>
<!-- //水平|垂直滚动条 -->
<div :class="['vscroll__bar vertical', {ishide: !isShow}]" @mousedown="handleClickTrack($event, 0)" :style="{'width': parseInt(size)>=0 ? parseInt(size)+'px' : '', 'z-index': parseInt(zIndex)>=0 ? parseInt(zIndex) : ''}">
<div class="vscroll__thumb" ref="ref__barY" :style="{'background': color, 'height': barHeight+'px'}" @mousedown="handleDragThumb($event, 0)"></div>
</div>
<div :class="['vscroll__bar horizontal', {ishide: !isShow}]" @mousedown="handleClickTrack($event, 1)" :style="{'height': parseInt(size)>=0 ? parseInt(size)+'px' : '', 'z-index': parseInt(zIndex)>=0 ? parseInt(zIndex) : ''}">
<div class="vscroll__thumb" ref="ref__barX" :style="{'background': color, 'width': barWidth+'px'}" @mousedown="handleDragThumb($event, 1)"></div>
</div>
</div>
</template>
/**
* @Desc VueJs虚拟滚动条组件VScroll
<script>
import domUtils from './utils/dom'
export default {
props: {
// 显示原生滚动条
native: Boolean,
// 自动隐藏滚动条
autohide: Boolean,
// 滚动条尺寸
size: { type: [Number, String], default: '' },
// 滚动条颜色
color: String,
// 滚动条层级
zIndex: null
},
data() {
return {
barWidth: 0, // 滚动条宽度
barHeight: 0, // 滚动条高度
ratioX: 1, // 滚动条水平偏移率
ratioY: 1, // 滚动条垂直偏移率
isTaped: false, // 鼠标光标是否按住滚动条
isHover: false, // 鼠标光标是否悬停在滚动区
isShow: !this.autohide, // 是否显示滚动条
}
},
mounted() {
this.$ref__box = this.$refs.ref__box
this.$ref__wrap = this.$refs.ref__wrap
this.$ref__barY = this.$refs.ref__barY
this.$ref__barX = this.$refs.ref__barX
this.$nextTick(this.updated)
},
// ...
methods: {
// 鼠标移入
handleMouseEnter() {
this.isHover = true
this.isShow = true
this.updated()
},
// 鼠标移出
handleMouseLeave() {
this.isHover = false
this.isShow = false
},
// 拖动滚动条
handleDragThumb(e, index) {
let _this = this
this.isTaped = true
let c = {}
domUtils.isIE() ? (e.returnValue = false, e.cancelBubble = true) : (e.stopPropagation(), e.preventDefault())
document.onselectstart = () => false
if(index == 0) {
c.dragY = true
c.clientY = e.clientY
}else {
c.dragX = true
c.clientX = e.clientX
}
domUtils.on(document, 'mousemove', function(evt) {
if(_this.isTaped) {
if(c.dragY) {
_this.$ref__wrap.scrollTop += (evt.clientY - c.clientY) * _this.ratioY
_this.$ref__barY.style.transform = `translateY(${_this.$ref__wrap.scrollTop / _this.ratioY}px)`
c.clientY = evt.clientY
}
if(c.dragX) {
_this.$ref__wrap.scrollLeft += (evt.clientX - c.clientX) * _this.ratioX
_this.$ref__barX.style.transform = `translateX(${_this.$ref__wrap.scrollLeft / _this.ratioX}px)`
c.clientX = evt.clientX
}
}
})
domUtils.on(document, 'mouseup', function() {
_this.isTaped = false
document.onmouseup = null;
document.onselectstart = null
})
},
// 滚动槽
handleClickTrack(e, index) {
console.log(index)
},
// 更新滚动
updated() {
if(this.native) return
// 垂直滚动条
if(this.$ref__wrap.scrollHeight > this.$ref__wrap.offsetHeight) {
this.barHeight = this.$ref__box.offsetHeight **2 / this.$ref__wrap.scrollHeight
this.ratioY = (this.$ref__wrap.scrollHeight - this.$ref__box.offsetHeight) / (this.$ref__box.offsetHeight - this.barHeight)
this.$ref__barY.style.transform = `translateY(${this.$ref__wrap.scrollTop / this.ratioY}px)`
}else {
this.barHeight = 0
this.$ref__barY.style.transform = ''
this.$ref__wrap.style.marginRight = ''
}
// 水平滚动条
...
},
handleResize() {
// 更新滚动条状态
},
// ...
}
}
</script>
vue中directives指令函数监听DOM变化。
// 监听元素/DOM尺寸变化
directives: {
'resize': {
bind: function(el, binding) {
let width = '', height = '';
function get() {
const elStyle = el.currentStyle ? el.currentStyle : document.defaultView.getComputedStyle(el, null);
if (width !== elStyle.width || height !== elStyle.height) {
binding.value({width, height});
}
width = elStyle.width;
height = elStyle.height;
}
el.__vueReize__ = setInterval(get, 16);
},
unbind: function(el) {
clearInterval(el.__vueReize__);
}
}
}
好了,今天就分享到这里。希望大家能喜欢哈!
基于vue.js网页弹窗组件|vue自定义对话框VLayer
链接:https://juejin.cn/post/6901103494971785223/
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。