weex手机端安全键盘
github地址:weexSafeKeyboard
效果图:
技术依赖:
框架:weex+vue
弹出层:weex-ui
图标:iconfont
说明:
1、如果不想用到weex-ui,可以把inputkey.vue文件里的wxc-popup组件去掉,按自己的弹窗实现即可;
2、删除、大小写、空格图标用的是iconfont;如不想用请自行替换;
本项目是放在本地,以安卓为例:android/app/src/main/assets/iconfont
3、密码可见、不可见图标按钮用的是common.js里的getImageUrl方法获取的路径,请自行替换
声明:
如有需要,请参考实现的思路,消化成自己的东西,勿直接复制,会消化不良。
实际调用页面:index.vue 代码如下:
<template>
<div>
<div class="cell">
<div class="cell_label">
<text class="label">密码</text>
</div>
<div class="cell_input">
<inputkey @inputVal="inputVal" :inputstyle="inputstyle" :textstyle="textstyle" type=true placeholder="请输入登录密码"></inputkey>
</div>
</div>
</div>
</template>
<style>
.cell {width: 750px;height: 120px;border-bottom-width: 2px;border-bottom-color: #C9C5C4;flex-direction: row;align-items: center;justify-content: center;}
.cell_label {justify-content: center;align-items: center;}
.label{font-size: 34px;font-weight: 600px;color:#000;}
.cell_input {justify-content: center;align-items: center;margin-left: 30px;}
</style>
<script>
import inputkey from './components/inputkey.vue';
export default {
data: {
inputstyle:{width:'550px',height:'50px',margin:'5px',fontSize:'36px'},
textstyle:{fontSize:'34px',fontWeight:'600',color:'#999'},
password:'',
},
components: {
inputkey
},
created: function () {
},
methods:{
inputVal(e){
this.password = e.inputVal;
}
}
}
</script>
组件:components/inputkey.vue 代码如下:
<template>
<div>
<div>
<div style="flex-direction:row;position:relative;" :style="inputstyle" @click="onfocus">
//placeholder内容
<text class="placeholder" v-if="blank">{{placeholder}}</text>
//把输入内容显示为*
<text v-if="type" :style="textstyle">{{passwordInput}}</text>
<text v-if="!type" :style="textstyle">{{input}}</text>
//光标“|”
<text v-if="cursor=='true'" :style="mrTextstyle" style="color:blue;">|</text>
//可不可见图标
<div class="imagearea" @click="lookPwd">
<image :src="imageUrl" class="image"></image>
</div>
</div>
</div>
//weex-ui 里的 wxc-popup 弹窗,可改为自己的
<wxc-popup popup-color="#fff"
:show="isBottomShow"
@wxcPopupOverlayClicked="popupMenu"
pos="bottom"
:height="popupHeight">
<div class="title">
<div class="btn" @click="changeState('abc')">
<text>Abc</text>
</div>
<div class="btn" @click="changeState('symbol')">
<text>符</text>
</div>
<div class="btn" @click="changeState('num')">
<text>123</text>
</div>
<div class="btn2" @click="randomAbc">
<text>安全键盘</text>
</div>
<div class="btn" @click="popupMenu">
<text>完成</text>
</div>
</div>
<div class="content">
//abc界面
<div class="row" v-for="item in charList" v-if="state == 'abc'">
<div class="button" v-for="ite in item" @click="ite=='top'?lowerToUpper(): btnClick(ite)">
<text v-if="ite === 'top'" style="fontFamily:iconfont;color:red;" v-bind:style="{backgroundColor:charState=='lower'?'':'#999999'}">&#xe685;</text>
<text v-else-if="ite === 'blank'" style="fontFamily:iconfont;color:red;">&#xe66e;</text>
<text v-else-if="ite === 'del'" style="fontFamily:iconfont;color:red;">&#xe629;</text>
<text v-else>{{ite}}</text>
</div>
</div>
//特殊符号界面
<div class="row" v-for="item in symbolList" v-if="state == 'symbol'">
<div class="button" v-for="ite in item" v-bind:style="{flex:ite==='blank'?6:1}" @click="btnClick(ite)">
<text v-if="ite === 'blank'" style="fontFamily:iconfont;color:red;">&#xe66e;</text>
<text v-else-if="ite === 'del'" style="fontFamily:iconfont;color:red;">&#xe629;</text>
<text v-else>{{ite}}</text>
</div>
</div>
//数字界面
<div class="row" v-for="item in numList" v-if="state == 'num'">
<div class="button" v-for="ite in item" v-bind:style="{flex:ite==='blank'?6:1}" @click="btnClick(ite)">
<text v-if="ite === 'blank'" style="fontFamily:iconfont;color:red;">&#xe66e;</text>
<text v-else-if="ite === 'del'" style="fontFamily:iconfont;color:red;">&#xe629;</text>
<text v-else>{{ite}}</text>
</div>
</div>
</div>
</wxc-popup>
</div>
</template>
<style>
.placeholder{color:#999999;font-size:36px;}
.title{flex-direction:row;justify-content:space-between;align-items:center;padding:10px;border-bottom-width:1px;}
.btn{height:70px;flex:1;align-items:center;justify-content:center;}
.btn2{height:70px;flex:4;align-items:center;justify-content:center;}
.content{padding-top:10px;padding-left:10px;}
.row{flex-direction:row;}
.button{height:65px;border-width:1px;flex:1;justify-content:center;align-items:center;margin-right:10px;margin-bottom:10px;padding-top:10px;padding-bottom:10px;}
.button:active{background-color: #999999;}
.image{width:48px;height:32px;}
.imagearea{width:48px;height:32px;position:absolute;top:9px;right:0;}
</style>
<script>
import common from '../common/common';
import { WxcPopup } from 'weex-ui';
var domModule = weex.requireModule('dom');
export default {
props: {
inputstyle:Object,
textstyle:Object,
type:{
type: Boolean,
default: true
},
placeholder:{
type: String,
default: '请输入密码'
}
},
components: {WxcPopup},
data: function(){
return {
input:'', //实际输入值
passwordInput:'', //实际输入值转为*
char: ['q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p','a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', 'z', 'x', 'c', 'v', 'b', 'n', 'm'],
charInit: [],
symbolList: [
['&','"',';','^',',','|','$','*',':','\''],
['?','{','[','~','#','}','.',']','\\','!'],
['(','%','-','_','+','/',')','=','<','`'],
['>','@','blank','del']
],
num:['1','2','3','4','5','6','7','8','9','0'],
numInit:[],
charRandom:'0', //字母随机标记
numRandom:'0', //数字随机标记
state:'abc',
charState:'lower',
isBottomShow:false,
popupHeight:'400',
cursor:'',
interval:'',
blank:true,
imageUrl:''
}
},
created: function () {
var self = this;
//字母初始值深拷贝
self.charInit = common.copy(self.char,'deep');
//数字初始值深拷贝
self.numInit = common.copy(self.num,'deep');
//iconfont引入
domModule.addRule('fontFace',{
'fontFamily':'iconfont',
//调用本地ttf
'src':"url('local:///iconfont/iconfont.ttf')"
});
//可不可见图片,可改变自己的
self.imageUrl=common.getImageUrl(self)+'login/bukejian.png';
},
methods:{
//聚焦事件,控制光标闪烁
onfocus(){
var self = this;
self.blank = false;
this.interval = setInterval(function() {
if(self.cursor == 'true'){
self.cursor = ''
}else{
self.cursor = 'true'
}
},500);
this.isBottomShow = true;
},
//关闭弹窗,取消闪烁
popupMenu(){
clearInterval(this.interval);
this.cursor = '';
this.isBottomShow = false;
this.$emit('inputVal', { inputVal: this.input });
if(!this.input){
this.blank = true;
}
},
//数组数据随机,恢复
randomArr(arr, name, init){
var self = this;
if(Array.isArray(arr)){
if(self[name] == '0'){
self[name] = '1';
return arr.sort(function() {
return (0.5-Math.random());
});
}else{
self[name] = '0';
self.charState = 'lower';
return common.copy(self[init],'deep');
}
}else{
return arr;
}
},
//安全键盘点击事件
randomAbc(){
var self = this;
if(this.state == 'abc'){
this.char = this.randomArr(this.char, 'charRandom', 'charInit');
}else if(this.state == 'num'){
this.num = this.randomArr(this.num, 'numRandom', 'numInit');
}
},
//大小写转换
lowerToUpper(){
var self = this;
var arr = [];
for(var i=0;i<self.char.length;i++){
if(self.char[i] >= 'a' && self.char[i] <= 'z'){
arr[i] = self.char[i].toUpperCase();
self.charState = 'upper';
}else{
arr[i] = self.char[i].toLowerCase();
self.charState = 'lower';
}
}
self.char = arr;
},
//字母、符号、数字切换事件
btnClick(ite){
if(ite == 'blank'){
this.input += ' '
this.passwordInput += '*'
}else if(ite == 'del'){
this.input = this.input.slice(0,this.input.length -1);
this.passwordInput = this.passwordInput.slice(0,this.passwordInput.length -1)
}else{
this.input += ite;
this.passwordInput += '*'
}
},
changeState(state){
this.state = state;
},
//密码可不可见切换
lookPwd(){
var self = this;
this.isBottomShow=false;
this.type=!(this.type);
self.imageUrl=common.getImageUrl(self)+(self.type?'login/bukejian.png':'login/kejian.png');
}
},
computed: {
//字母页面动态数据
charList () {
var self = this;
var arr = [];
arr[0] = ['1','2','3','4','5','6','7','8','9','0',];
arr[1] = self.char.slice(0,10);
arr[2] = ['top'].concat(self.char.slice(10,19));
arr[3] = ['blank'].concat(self.char.slice(19,26)).concat(['del']);
return arr;
},
//数字页面动态数据
numList(){
var self = this;
var arr = [];
arr[0] = self.num.slice(0,3);
arr[1] = self.num.slice(3,6);
arr[2] = self.num.slice(6,9);
arr[3] = ['.'].concat(self.num.slice(9,10)).concat(['del']);
return arr;
},
//光标的样式同输入字体样式相同,颜色为蓝色
mrTextstyle(){
const {textstyle} =this;
const mrBtnStyle = {
...textstyle, color: "blue"
};
return mrBtnStyle;
}
}
}
</script>
公用方法:common/common.js 代码如下:
exports.bundleUrl = function (self) {
var bundleUrl = self.$getConfig().bundleUrl;
return bundleUrl;
};
//判断系统,安卓返回'android',ios返回'iOS',h5返回'web'
exports.androidOrIos = function (self) {
return self.$getConfig().env.platform;
};
//获取图片完整路径前缀
exports.getImageUrl = function (self) {
var androidOrIos = this.androidOrIos(self);
var bundleUrl = this.bundleUrl(self);
var isHttp = bundleUrl.indexOf('http://') >= 0;
var imageUrl;
if (isHttp) {
var i = bundleUrl.indexOf('/dist/');
if (androidOrIos == "android") {
imageUrl = bundleUrl.slice(0, i) + '/images/';
} else if (androidOrIos == "iOS") {
imageUrl = bundleUrl.slice(0, i) + '/images.bundle/';
}
} else {
if (androidOrIos == "android") {
imageUrl = 'assets:';
} else if (androidOrIos == "iOS") {
var i = bundleUrl.indexOf('XDPT.app');
//vue语法中读取图片资源放在.bundle文件中
//不然会出现The requested URL was not found on this server.
imageUrl = bundleUrl.slice(0, i + 8) + '/images.bundle/';
}
}
return imageUrl;
}
//对象类型判断,下面深,浅拷贝用
//深浅拷贝来源百度,太懒没自己写
exports.util = (function () {
var class2type = {};
["Null", "Undefined", "Number", "Boolean", "String", "Object", "Function", "Array", "RegExp", "Date"].forEach(function (item) {
class2type["[object " + item + "]"] = item.toLowerCase();
})
function isType(obj, type) {
return getType(obj) === type;
}
function getType(obj) {
return class2type[Object.prototype.toString.call(obj)] || "object";
}
return {
isType: isType,
getType: getType
}
})();
//对象深,浅拷贝
exports.copy = function (obj, deep) {
if (obj === null || typeof obj !== "object") {
return obj;
}
var i, target = this.util.isType(obj, "array") ? [] : {}, value, valueType;
for (i in obj) {
value = obj[i];
valueType = this.util.getType(value);
if (deep && (valueType === "array" || valueType === "object")) {
target[i] = this.copy(value);
} else {
target[i] = value;
}
}
return target;
}
原文地址:https://segmentfault.com/a/1190000013109794
weex手机端安全键盘的更多相关文章
- JS自定义手机端H5键盘
在输入车牌号的时候,因为很多车牌号都是数字字母混合排列的,所以如果用输入法输入就需要频繁切换数字跟字母,有点麻烦. 在这里我们就用自定义一个弹出框代替键盘来使用. 1.首先,要禁止掉文本框弹出输入法, ...
- HTML 在安卓手机端软键盘弹出顶起页面布局的解决办法
$('body').height($('body')[0].clientHeight); 以上是背景即BODY被顶起的解决办法. 如果是footer被顶起,则可以用判断解决, $('input').f ...
- delphi 键盘常用参数(PC端和手机端 安卓/IOS)
常数名称(红色手机端) 十六进制值 十进制值 对应按键(手机端) Delphi编程表示(字符串型)_tzlin注 0 0 大键盘Delete键 #0 VK_LBUTTON 1 1 鼠标的左键 #1 V ...
- [UWP小白日记-15]在UWP手机端实时限制Textbox的输入
说实话重来没想到验证输入是如此的苦逼的一件事情. 网上好多验证都是在输入完成后再验证,我的想法是在输入的时候就限制输入,这样我就不用再写代码来验证了 应为是手机端,所以不用判断其他非法字符,直 ...
- 移动端调试神器vconsole,手机端网页的调试工具Eruda
移动端调试神器vconsole,手机端网页的调试工具Eruda 移动端中使用 vConsole调试 移动端调试工具vconsole安装Git地址:https://github.com/WechatFE ...
- 使用localResizeIMG3+WebAPI实现手机端图片上传
前言 惯例~惯例~昨天发表的使用OWIN作为WebAPI的宿主..嗯..有很多人问..是不是缺少了什么 - - 好吧,如果你要把OWIN寄宿在其他的地方...代码如下: namespace Conso ...
- 《JS实现复制内容到剪贴板功能,可兼容所有PC浏览器,不兼容手机端》
前记:本来原生的JS是有提供一个函数来实现这个功能(window.clipboardData),但是很遗憾,这个函数仅仅支持IE和FF浏览器,所以基本用处不大.下边介绍的是一个第三方插件库(ZeroC ...
- 【极品代码】一般人我不告诉他,手机端h5播放时不自动全屏代码
已测适用于ios,某些安卓手机微信下播放视频会出现播放器控件(这个实在是无力吐槽噢,因为之前还遇到过微信播放完视频后竟然无法退出全屏出现广告的情况,只有播放完后刷新页面并且要放到框架页里才能屏蔽微信视 ...
- 判断是pc端还是手机端,并跳转到相应页面
<!-- 判断浏览器是否为手机端 --> <script> // class ! function(navigator) { var user ...
随机推荐
- Linux文字分段裁剪命令cut(转)
Linux cut命令用于显示每行从开头算起num1到num2的文字. 语法 cut [-bn] [file] cut [-c] [file] cut [-df] [file] 使用说明: cut命令 ...
- Light oj 1251 - Forming the Council 【2-sat】【推断是否存在可行解 + 反向拓扑输出可行解】
1251 - Forming the Council problem=1251" style="color:rgb(79,107,114)"> PDF (Engli ...
- Java与设计模式-策略模式
在实际开发中,可能会遇到这样一个情况,某一功能的实现分为多种算法,这些算法能够认定为策略,在实际操作时选择不同算法或策略进行操作得出终于结果.在实际生活中.这些样例也是举不胜举.比如.商场举行活动,满 ...
- React-Native Android开发沉思录
在runServer.js中有声明如何启动http服务: 查看端口占用情况 而且在系统管理器中,根本找不到PID为7956的应用,那能更改端口吗?在server.js中有声明: module.expo ...
- 使用串口终端安装AIX操作系统
使用串口终端安装AIX操作系统 一.配置超级终端 首先,配置超级终端:在笔记本电脑上(Windows XP系统),点击开始à程序->附件->通讯->超级终端,配置名称为test的超级 ...
- [Plugin] JQuery.uploadify上传文件插件的使用详解For ASP.NET
URL:http://www.cnblogs.com/xiaopin/archive/2010/01/21/1653523.html 今天下午整理文件上传的例子,感觉收集到的例子都很不人性话,后来找到 ...
- TCP心跳包
所谓的心跳包就是客户端定时放送简单的信息给服务器端,告诉它我还在而已.代码就是每 隔几分钟发送一个固定信息给服务器端,服务器端回复一个固定信息.如果服务器端几分钟后没有收到客户端信息则视客户端断开.比 ...
- Dvwa安装,配置(Linux)
文章演示使用系统:CenTOS7 一:搭建LAMP环境 使用XAMPP安装部署,下载地址:https://www.apachefriends.org/download.html 1.1:赋予账号对XA ...
- Java Break和continue实现goto功能
continue实验 1 public class test { static int i =0; public static void main(String[] args) { lable1: w ...
- React+webpack
webPack + React 步骤: 1. 创建文件夹 src 源代码目录 main.js 打包的入口文件 App.js 项目的根组件 import React,{Component} from ' ...