如果您想订阅本博客内容,每天自动发到您的邮箱中, 请点这里
5.0以后,materialDesign风格,出现了立体这种概念,高光,阴影,也就是Z轴,凸显层次;同时,裁剪view也变得方便简单了很多。
1,先说说阴影的实现。
方案1:在xml中设置
xml中设置有两个方式,android:elevation="2dp"
android:translationZ="2dp"这两句代码是可以同时并存的,而且是叠加的效果;当然只使用其中一个属性进行z轴的阴影设置也是OK的。
方案2:在代码中设置
(下面说这个实现方式,其实就是轮廓的实现)
设置阴影,有一个需要注意的地方:
①:view的大小要比它的父布局小,才会有阴影效果,如果相同大小,是看不到阴影效果的;
②:给图片设置阴影的时候,如果这种图片的background属性是shape,那直接通过xml设置阴影是OK的,但是,如果是一张png或者其他格式的图片,直接通过xml设置android:elevation="2dp"
android:translationZ="2dp"阴影是看不到效果的,得通过其他代码设置才行。。。**
2,view的轮廓,轮廓其实也是阴影
默认情况下,所有的view都是矩形的,虽然可以给view设置背景圆形的图片,即可以在界面显示出圆形的内容,但是view的大小实际上依然是矩形,并且设置的图片实际上也是矩形的,只是圆形以外的区域是透明色。
如果根据view大小来生成对应的阴影,就会出现很奇怪的效果,(一个看起来圆形的view展示出的确实一个矩形的阴影)我了解决这个问题,view增加了一个新的描述来指明内容显示的形状,这就是 轮廓
轮廓的实现
①通过shape设置的背景,view会自动根据shape的形状进行轮廓判定,
②通过color设置的背景,view默认其轮廓和view的大小一样。
③但是通过图片进行背景设置,view则无法获知轮廓的形状,这个时候就需要手动进行指定了。
1
2
3
一:在xml中可以通过android:outlineProvider来指定轮廓的判定方式:
1,none即使设置了Z属性,也不会显示阴影
2,background会按照背景来设置阴影形状
3,bounds会按照view的大小来描绘阴影
**对于①和②这种情况,也是可以通过设置`android:outlineProvider`
来改变阴影的形状以及轮廓外观的。**
对于③这种背景是一张png或者其他格式的图片的情况,
`android:outlineProvider=“background”`
是没有效果的,属性设置成`android:outlineProvider=bounds`
虽然也是有效果的,但是阴影轮廓是一个方形的轮廓,
并不是我们想要的效果了。
不设置`android:outlineProvider`属性就更没有效果了。
1
2
3
4
5
6
7
8
9
10
对于这种使用了png图片作为背景的view加阴影轮廓的时候情况解决办法也非常简单,解决办法就是:
就通过Java代码设置,也就是说,一个圆形的png图(我们知道,看起来是圆形的,
但是它其实还是方形的图片,只是圆形之外的区域是透明不可见的),
通过Java代码设置轮廓,就会显示出圆形的阴影轮廓了。
1
2
3
具体实现,继续看:
二:在代码中,课通过setOutlineProvider来指定一个view的轮廓。
对于③这种情况在代码中设置轮廓才会有效果。
TextView textView= findViewById(R.id.tv);
ViewOutlineProvider viewOutlineProvider=new ViewOutlineProvider() {
@Override
public void getOutline(View view, Outline outline) {
//x,y轴表示位置,后两个参数表示长,宽
outline.setOval(0,0,textView.getWidth(),textView.getHeight());
}
};
textView.setOutlineProvider(viewOutlineProvider);
1
2
3
4
5
6
7
8
9
强调:
如果采用圆形图片作为背景,即使在xml布局中指定android:outlineProvider=“background”,也不会显示阴影,设置为android:outlineProvider=bounds,虽然也有效果,但是效果很差,所以一般都是通过代码来指定轮廓显示。
1,一个shape圆形作为背景,设置阴影,设置android:outlineProvider的4种属性的效果:
2,一个圆形png作为背景,设置阴影,设置android:outlineProvider的4种属性的效果:
3,一个png作为背景,设置阴影,通过代码设置的效果:
3,view的裁剪
裁剪,默认的ImageView是矩形的,很多时候,需要的是圆角的ImageView或者圆形的ImageView,这就需要裁剪view了。
实现,裁剪圆形:
final TextView textView= findViewById(R.id.tv);
ViewOutlineProvider viewOutlineProvider=new ViewOutlineProvider() {
@Override
public void getOutline(View view, Outline outline) {
//设置圆形oval
outline.setOval(0,0,textView.getWidth(),textView.getHeight());
}
};
//设置裁剪
textView.setClipToOutline(true);
1
2
3
4
5
6
7
8
9
10
11
实现,裁剪圆角矩形:
final TextView textView= findViewById(R.id.tv);
ViewOutlineProvider viewOutlineProvider=new ViewOutlineProvider() {
@Override
public void getOutline(View view, Outline outline) {
//设置圆角矩形
outline.setRoundRect(0,0,view.getWidth(),view.getHeight(),25);
}
};
textView.setOutlineProvider(viewOutlineProvider);
//设置裁剪
蓝蓝设计( www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 、平面设计服务。
如果您想订阅本博客内容,每天自动发到您的邮箱中, 请点这里
一、简介
TabLayout提供了一个水平布局用于展示tabs,继承自HorizontalScrollView。一般与Viewpager结合使用实现页面和标签联动的效果,是时下APP中非常常用的一个控件
二、基本用法
如果您想订阅本博客内容,每天自动发到您的邮箱中, 请点这里
jQuery对Ajax操作进行了封装,常用的方法包括 $.get(),$.post(),$.ajax()。
分别对其进行介绍
$.get()
$.get()方法使用GET方式来进行异步请求。
$.get()结构
$.get(url,[. data][. callback][. type])
1
$.get()方法参数解释
参数名称 类型 说明
url String 请求的HTML页的url地址
data(可选) Object 发送至服务器的key/value数据会作为QueryString附加到请求的url中
callback(可选) Function 载入成功时回调函数(只有当Response的返回状态是success才调用该方法)自动将请求结果和状态传递给该方法
type(可选) String 服务器端返回内容的格式,包括xml、html、script、json、text和_default
示例
json数据:data.json(后面的$.post()和$.ajax()方法都用这个数据)
{
"name":"龙猫",
"hobby":"睡觉",
"friend":"加菲猫"
}
jq_get.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<input type="button" value="$.get方法" id="jQget">
<div id="content"></div>
</body>
</html>
<!-- 导入jquery.js文件 -->
<script type="text/javascript" src="js/jquery.min.js"></script>
<script type="text/javascript">
$(function(){
$('#jQget').on('click',function(){
/*
参数1:url
参数2:发送的数据 支持 直接写js对象的方式
参数3:回调函数
参数4:从服务端获取的 数据类型 可以不写
注意
如果type 为json
并且服务端返回的就是 json格式字符串
jq内部 会帮助我们自动转化
在回调函数中 获取的 实参 就是转化完成的 js对象 直接使用即可
参数的 顺序 是更换的
但是 如果 把data 放到后面 会出现 无法传递数据的问题,
所以 不要擅自更换 严格按照 jq文档中的 顺序 进行使用
*/
$.get('jq_get.php',{name:"jack",age:18},function(data){
console.log(data);
$('#content').html('name:'+data.name+'<br>'+'hobby:'+data.hobby+'<br>'+'friend:'+data.friend);
},'json');
});
});
</script>
jq_get.php (后面的$.post()和$.ajax()方法都用这个页面的内容,只是在html请求时分别对应的php页面)
<?php
header('content-type:text/html;charset=utf-8');
echo file_get_contents('datas/data.json');
?>
结果展示:
$.post()方法
它与$.get()方法的结构和使用方式都相同,不过它们之间仍然有以下区别:
GET请求会将参数跟在URL后进行传递,而POST请求则是作为HTTP消息的实体内容发送个Web服务器,当然,在Ajax中,这种区别对用户是不可见的。
GET方式对传输的数据有大小限制(通常不能大于2KB),而使用POST方式传递的数据量要比GET方式大得多(理论上不受限制,但是可以在服务端进行限制)。
GET方式请求的数据会被浏览器缓存起来,因此其他人就可以从浏览器的历史记录中读取这些数据,例如账号和密码等。在某种情况下,GET方式会带来严重的安全性问题,而POST方式相对来说就可以避免这些问题。(但是也是不安全的,所以密码之类的还是要加密的)
GET方式和POST方式传递的数据在服务器的获取方式也不相同。在PHP中,GET方式数据可以用$_GET[]获取,而POST可以用$_POST[]获取、两种方式都可以用$_REQUEST[]来获取。
其实这完全是对这篇文章中post()和get()方法不同的总结啊!(点击查看)
$.post()演示
<script type="text/javascript" src="js/jquery.min.js"></script>
<script type="text/javascript">
$(function(){
$('#jQpost').on('click',function(){
// 跟$.get用法及其类似
/*
参数1:url
参数2:发送的数据 支持 直接写js对象的方式
参数3:回调函数
参数4:从服务端获取的 数据类型 可以不写,如果写为json jq内部 会帮我们进行一个 JSON.parse()的转化
*/
$.post('jq_post.php',{name:"kong",age:18},function(data){
console.log(data);
},'json');
});
});
</script>
$.ajax()
$.ajax()方法是jQuery最底层的Ajax实现
其结构为
$.ajax(options)
1
该方法只有1个参数,但在这个对象里包含了$.ajax()方法所需要的请求设置以及回调函数等信息,参数以key/value的形式存在,所有参数都是可选的,只写几个常用的参数,如下:
参数名称 类型 说明
url String 请求的HTML页的url地址
type String 请求方式,默认GET。注意其他的HTTP请求方法,例如PUT和DELETE也可以使用,但仅部分浏览器支持
data Object或String 发送到服务器的数据,如果已经不是字符串,将自动转换为字符串格式。
dataType String 服务器端返回内容的格式,包括xml、html、script、json、jsonp 、jQuery
beforeSend Function 发送请求前可以修改XMLHttpRequest对象的函数,例如添加自定义HTTP头。在beforeSend中如果返回false可以取消本次Ajax请求。XMLHttpRequest对象的唯一参数。
success Function 请求成功后嗲用的回调函数,有两个参数。
(1)由服务器返回,并根据dataType参数进行处理后的数据。
(2)描述状态的字符串。
function(data,textStatus){
//data可能是xmlDoc、jsonObj、html、text等等。
this//调用本次Ajax请求时传递的options参数
}
error Function 请求失败时被调用的函数,该函数有3个参数,即
XMLHttpRequest对象、错误信息、捕获的错误对象(可选)。
Ajax事件函数如下。
function(XMLHttpRequest,textStatus,errorThrown){//通常情况下textStatus和errorThown只有其中一个包含信息
this;//调用本次Ajax请求时传递的options参数
}
示例
<script type="text/javascript" src="js/jquery.min.js"></script>
<script type="text/javascript">
$(function(){
$('#jqAjax').on('click',function(){
/*
常见参数:
url:请求的地址
success:请求成功的回调函数
type:不写是get 可以指定 get,post
dataType:数据的类型
data:发数据 可以写js对象
beforeSend:发送之前调用的匿名函数
可以return false 阻止该次请求
验证用户的数据 是否填了
error:请求失败以后 会调用
*/
$.ajax({
url:'jq_ajax.php',
success:function(data){
console.log(data);
$('#box').append(data.name+'<br>'+data.hobby);
},
type:'post',
dataType:'json',
data:{"name":"张信哲","skill":"情歌王子"},
beforeSend:function(){
console.log('发送之前调用');
},
error:function(){
console.log('请求失败了');
}
});
});
});
</script>
---------------------
作者:diligentkong
来源:CSDN
原文:https://blog.csdn.net/diligentkong/article/details/72851443
版权声明:本文为博主原创文章,转载请附上博文链接!
蓝蓝设计( www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 、平面设计服务。
如果您想订阅本博客内容,每天自动发到您的邮箱中, 请点这里
之前研究了定位,想用百度地图,但是用百度地图的
JavaScript API里面的浏览器定位根本不行,要用插件,很多人说本身带的这个cordova-plugin-geolocation插件因为网络问题,只有ios可以用,然后找到了专门针对安卓的cordova-qdc-baidu-location插件,但是这个插件不知道是不是我使用的问题,得到的数据可以弹出来,但是数据并不像这个插件所说的数据格式是
{
latitude : 纬度,
lontitude: 经度, ... }
这样的,而是字符串,不是json字符串,弄了半天还是取不到里面的关于经纬度的值,然后发现了现在的这个定位插件cordova-plugin-baidumaplocation这个插件返回的数据格式是json的,可以直接获取。
因为网络配代理的原因,一直添加不上插件,今天才发现用cordova-plugin-baidumaplocation插件定位其实挺简单的。
1.申请AK值。
地址:http://lbsyun.baidu.com/
需要申请两个或者三个(配置ios),一个是js的,一个是android的(三个的话还有一个ios的,但是这边直接只写安卓的,其实ios是一样的)
注:包名要一致
2.添加插件.
命令:
cordova plugin add cordova-plugin-baidumaplocation --variable ANDROID_KEY="<API_KEY_ANDROID>" --variable IOS_KEY="<API_KEY_IOS>"
注意:是没有<>这种尖括号的。
到此为止准备工作基本上晚了,开始代码部分:
1.引入百度地图:
<script type="text/javascript" src="http://api.map.baidu.com/api?v=2.0&ak=nLsK9qUii8uBZlkPAQUozAf9mR5xNVZF"></script>
这个引入是为了转化经纬度为地址和显示地图。
2.在html页面上写两个 标签:
<button class="button" ng-click="getarea()">点击我获取地址百度</button> <div id='allmap' style=""></div>
div标签是为了放地图的。
3.js部分:
$scope.getarea=function(){ //myaddr(116.324499,39.899216); // 进行定位 baidumap_location.getCurrentPosition(function (result) { var latitude=result.latitude; var lontitude=result.lontitude;
myaddr(lontitude,latitude);
}, function (error) { });
} //根据定位得到的经纬度对地址进行解析 function myaddr(lontitude,latitude){ //alert("我的地址是:"+lontitude+","+latitude); // 百度地图API功能 var map = new BMap.Map("allmap"); var point = new BMap.Point(lontitude, latitude);//34.7534880000,113.6313490000 map.centerAndZoom(point, 12); var marker = new BMap.Marker(point); // 创建标注 map.addOverlay(marker); // 将标注添加到地图中 //把地址在地图上标出来 var geoc = new BMap.Geocoder();
geoc.getLocation(point, function(rs){ var addrmsg=rs.address; //var addComp = rs.addressComponents; //详细的分省市县街道的信息 //alert(addComp.province + ", " + addComp.city + ", " + addComp.district + ", " + addComp.street + ", " + addComp.streetNumber); var opts = {
width : 200, // 信息窗口宽度 height: 50, // 信息窗口高度 } var infoWindow = new BMap.InfoWindow("地址:"+addrmsg, opts); //创建信息窗口对象 map.openInfoWindow(infoWindow,point); //开启信息窗口 });
}
4.css部分:其实可以不要的,这是因为地图中的地址显示的窗口看起来有点问题,虽然改了依旧不好看,但是功能实现了。
.BMap_pop{ top: 70px !important; } .BMap_bubble_content{ width: 95% !important; } .BMap_center{ top: 26px !important; }
注:现在得到的地址是省市县街道地址,想得到诸如:北京市朝阳区XX大厦附近这样的地址的话还没有研究,等研究出来了再补上。
蓝蓝设计( www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 、平面设计服务。
如果您想订阅本博客内容,每天自动发到您的邮箱中, 请点这里
了解一个技术,首先要了解这个技术产生的背景及解决的问题,而不应该只是单纯的知道该怎么用。之前的状态可能就是只是为了了解而了解,并不知道实际产生的原因及带来的好处,所以今天就来总结一下。
来看百度百科的定义
模块化程序设计是指在进行程序设计时将一个大程序按照功能划分为若干小程序模块,每个小程序模块完成一个确定的功能,并在这些模块之间建立必要的联系,通过模块的互相协作完成整个功能的程序设计方法。
比如 java 的 import,C# 的 using。我的理解是通过模块化编程,可以将不同的功能独立出来,修改某个功能时不会对其他功能产生影响。
来看下面一个例子
// A.js function sayWord(type){ if(type === 1){
console.log("hello");
}else if(type === 2){
console.log("world");
}
} // B.js function Hello(){ sayWord(1);
} // C.js Hello()
假设上面三个文件,B.js 引用了 A.js 里面的内容,C.js 又引用了 B.js 里面的内容,如果编写 C.js 的人只知道引用了 B.js,那他就不会引用 A.js 就会导致程序出错,而且文件的引用顺序也不能出错。给整体代码的调试修改带来不便。
还有个问题,上述代码暴露了两个全局变量,容易造成全局变量的污染
AMD 即 Asynchronous Module Definition(异步模块定义)。采取异步加载的方式加载模块,模块的加载不会影响它后面的语句执行。而且只有用到的时候才会去加载相关文件,属于浏览器端的标准
假设下面这种情况
// util.js define(function(){ return {
getFormatDate:function(date,type){ if(type === 1){ return '2018-08-9' } if(type === 2){ return '2018 年 8 月 9 日' }
}
}
}) // a-util.js define(['./util.js'],function(util){ return {
aGetFormatDate:function(date){ return util.getFormatDate(date,2)
}
}
}) // a.js define(['./a-util.js'],function(aUtil){ return {
printDate:function(date){ console.log(aUtil.aGetFormatDate(date))
}
}
}) // main.js require(['./a.js'],function(a){ var date = new Date()
a.printDate(date)
})
console.log(1); // 使用 // <script src = "/require.min.js" data-main="./main.js"></script>
页面上先打印 1
,然后才会打印 2018 年 8 月 9 日
。因此 AMD 的加载并不会影响后续的语句执行。
如果不是异步加载会出现什么情况呢
var a = require('a');
console.log(1)
后面的语句需要等待 a 加载完成才能执行,如果加载时间过长,整个程序都会卡在这。因此,浏览器不能同步加载资源,这也是 AMD 的产生背景。
AMD 是在浏览器端实现模块化开发的规范。由于该规范不是 JavaScript 原始支持的,使用 AMD 规范进行开发的时候需要引入第三方的库函数,也就是 RequireJS。
RequireJS 主要解决的问题
下面来看看如何使用 require.js
要想使用 require.js,首先要 define
// ? 代表该参数可选 define(id?, dependencies?, factory);
factory:为模块初始化要执行的函数或对象。如果为函数,它应该只被执行一次。如果是对象,此对象应该为模块的输出值。
具体的规范说明可以参考 AMD (中文版)
举个例子,创建一个名为 “alpha” 的模块,使用了 require,exports,和名为 “beta” 的模块:
define("alpha", ["require", "exports", "beta"], function (require, exports, beta) { exports.verb = function() { return beta.verb(); //Or: return require("beta").verb();
}
});
一个返回对象的匿名模块:
define(["alpha"], function (alpha) { return {
verb: function(){ return alpha.verb() + 2;
}
};
});
一个没有依赖性的模块可以直接定义对象:
define({
add: function(x, y){ return x + y;
}
});
如何使用
AMD 采用 require 语句加载模块
require([module],callback);
例如
require(['./a.js'],function(a){ var date = new Date()
a.printDate(date)
})
具体的使用方法如下
// util.js define(function(){ return {
getFormatDate:function(date,type){ if(type === 1){ return '2018-08-09' } if(type === 2){ return '2018 年 8 月 9 日' }
}
}
}) // a-util.js define(['./util.js'],function(util){ return {
aGetFormatDate:function(date){ return util.getFormatDate(date,2)
}
}
}) // a.js define(['./a-util.js'],function(aUtil){ return {
printDate:function(date){ console.log(aUtil.aGetFormatDate(date))
}
}
}) // main.js require(['./a.js'],function(a){ var date = new Date()
a.printDate(date)
}) // 使用 // <script src = "/require.min.js" data-main="./main.js"></script>
假设这里有 4 个文件,util.js,a-util.js 引用了 util.js,a.js 引用了 a-util.js,main.js 引用了 a.js。
其中,data-main 属性的作用是加载网页程序的主模块。
上例演示了一个主模块最简单的写法,默认情况下,require.js 假设依赖和主模块在同一个目录。
使用 require.config()
方法可以对模块的加载行为进行自定义。require.config()
就写在主模块(main.js)的头部,参数是一个对象,这个对象的 paths 属性指定各个模块的加载路径
require.config({
paths:{ "a":"src/a.js", "b":"src/b.js" }
})
还有一种方法是改变基础目录(baseUrl)
require.config({
baseUrl: "src",
paths: { "a": "a.js", "b": "b.js",
}
});
commonJS 是 nodejs 的模块化规范,现在被大量用在前端,由于构建工具的高度自动化,使得使用 npm 的成本非常低。commonJS 不会异步加载 JS,而是同步一次性加载出来
在 commonJS 中,有一个全局性的方法 require(),用于加载模块,例如
const util = require('util');
然后,就可以调用 util 提供的方法了
const util = require('util'); var date = new date();
util.getFormatDate(date,1);
commonJS 对于模块的定义分三种,模块定义(exports),模块引用(require)和模块标示(module)
exports() 对象用于导出当前模块的变量或方法,唯一的导出口。require() 用来引入外部模块。module 对象代表模块本身。
举个栗子
// util.js module.exports = {
getFormatDate:function(date, type){ if(type === 1){ return '2017-06-15' } if(type === 2){ return '2017 年 6 月 15 日' }
}
} // a-util.js const util = require('util.js')
module.exports = {
aGetFormatDate:function(date){ return util.getFormatDate(date,2)
}
}
或者下面这种方式
// foobar.js // 定义行为 function foobar(){ this.foo = function(){ console.log('Hello foo');
} this.bar = function(){ console.log('Hello bar');
}
} // 把 foobar 暴露给其它模块 exports.foobar = foobar; // main.js //使用文件与模块文件在同一目录 var foobar = require('./foobar').foobar,
test = new foobar();
test.bar(); // 'Hello bar'
ES6 模块的设计思想是尽量静态化,使得编译时就能确定模块的依赖关系,以及输入和输出的变量,而 CommonJS 和 AMD 模块都只能在运行时确定这些关系。如 CommonJS 加载方式为 “运行时加载”,ES6 的加载方式为 “编译时加载” 或者静态加载,即 ES6 可以在编译时就完成模块加载,效率比 CommonJS 模块的加载方式高。
ES6 模块自动采用严格模式,不管有没有在模块头部加上 “use strict”。
ES6 export 语句输出的接口与其对应的值是动态绑定关系,即通过该接口可以取到模块内部实时的值。而 CommonJS 模块输出的是值的缓存,不存在动态更新。
ES6 与 CommonJS 模块的差异
第二个差异是因为 CommonJS 加载的是一个对象(即 Module.exports 属性),该对象只有在脚本运行结束时才会生成,而 ES6 模块不是对象,它的对外接口只是一种静态定义,在代码静态解析阶段就会生成。
CommonJS 采用了服务器优先的策略,使用同步方式加载模块,而 AMD 采用异步加载的方式。所以如果需要使用异步加载 js 的话建议使用 AMD,而当项目使用了 npm 的情况下建议使用 CommonJS。
蓝蓝设计( www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 、平面设计服务。
如果您想订阅本博客内容,每天自动发到您的邮箱中, 请点这里
在小程序里面有两个地方获取用户的openid。
一个是wx.login(OBJECT),第二个是wx.getUserInfo(OBJECT)。
这里我使用的是第一种wx.login(OBJECT)。
wx.login({
success: function(res) { if (res.code) { // 第一步: 获取code //发起网络请求 wx.request({
url: '后台接口', // 获取openid data: {
code: res.code
}
})
} else {
console.log('获取用户登录态失败!' + res.errMsg)
}
}
});
后端的实现就是后端调用这个接口:https://api.weixin.qq.com/sns/jscode2session?appid=APPID&secret=SECRET&js_code=JSCODE&grant_type=authorization_code。
/*
* 根据code获取微信用户的openid
*/ router.get('/api/getWxCode', function(req, res, next) { var param = req.query || req.params; var code = param.code; var urlStr = 'https://api.weixin.qq.com/sns/jscode2session?appid=' + wxConfig.AppID + '&secret=' + wxConfig.Secret + '&js_code=' + code + '&grant_type=authorization_code';
request(urlStr, function (error, response, body) { if (!error && response.statusCode == 200) { var jsBody = JSON.parse(body);
jsBody.status = 100;
jsBody.msg = '操作成功';
res.end(JSON.stringify(jsBody));
}
})
});
/**
* 生命周期函数--监听页面加载
*/ onLoad: function (options) { var self = this;
wx.login({
success: function (res) { if (res.code) { //发起网络请求 wx.request({
url: 'https://www.hgdqdev.cn/api/getWxCode',
data: {
code: res.code
},
success: function(res){ if(res.data.status == 100){ self.setData({
openid: res.data.openid
})
}
},
fail: function(){ }
})
} else {
console.log('获取用户登录态失败!' + res.errMsg)
}
}
});
},
蓝蓝设计( www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 、平面设计服务。
如果您想订阅本博客内容,每天自动发到您的邮箱中, 请点这里
我也是刚学自动化,在自学过程中发现浏览器中有一些弹窗元素,无法定位。经过自己的摸索,有一些心得,写下来供日后自己回顾。
首先要确定弹窗的类型:
(1)div弹窗
(2)新标签页弹窗
(3)alert弹窗
一,div弹窗
div弹窗是浏览器中比较好定位的弹窗,定位的方法与普通的元素一样。不过这里会有一个坑,明明可以找到这个按钮,但是就是定位不到。这个就是因为当前有div弹窗弹出的时候,需要设置一下等待时间,等页面元素加载完毕,再去做其他操作。
这里用百度登陆为例子:
from selenium import webdriver import time def login_baidu(url,username,password): driver.get(url)
driver.find_element_by_xpath('//*[@id="u1"]/a[7]').click()
time.sleep(2)
driver.find_element_by_xpath('//*[@id="TANGRAM__PSP_10__footerULoginBtn"]').click()
time.sleep(2) # 弹窗出现后,使页面等待2S login_username = driver.find_element_by_xpath('//*[@id="TANGRAM__PSP_10__userName"]')
login_username.click()
login_username.send_keys(username)
login_passwork = driver.find_element_by_xpath('//*[@id="TANGRAM__PSP_10__password"]')
login_passwork.click()
login_passwork.send_keys(password)
driver.find_element_by_xpath('//*[@id="TANGRAM__PSP_10__submit"]').click() # 登陆按钮 if __name__ == "__main__":
driver = webdriver.Firefox()
username = r'xxx@qq.com' password = r'xxxx' url = r'https://www.baidu.com' login_baidu(url,username,password)
二,新标签页弹窗
新标签页弹窗,则需要进行窗口的切换。此处第一个窗口打开百度首页,在打开一个新窗口打开京东首页,在两个窗口之间进行切换。切换到不同的窗口之后,就可以用常规的方法进行元素的定位。
from selenium import webdriver import time def open_window1(): driver.get("https://www.baidu.com")
time.sleep(2) def open_window2(): # 用JS的方法打开新窗口,模拟新标签页弹窗 js = "window.open('https://www.jd.com')" driver.execute_script(js)
time.sleep(2) def Switch_Window(): handles = driver.window_handles
print("打印当前已打开的窗口:"+str(handles)) while(5): # 在两个窗口之间做五次切换动作 driver.switch_to.window(handles[0])
time.sleep(5)
driver.switch_to.window(handles[1])
time.sleep(5) if __name__ == "__main__" :
driver = webdriver.Firefox()
open_window1()
open_window2()
Switch_Window()
handles = driver.window_handles # 获取当前打开的所有窗口的句柄
driver.switch_to.window(handles[N]) # 切换到其中一个窗口
其中,获取的句柄下标从0开始,即第一个窗口为[0]、第二个窗口为[1],如此类推。使用switch_to.window方法切换到新标签页后就可以做其他操作了。
三、alert弹窗
该类型的弹窗暂没有合适的项目进行练习,待后续完善
如果您想订阅本博客内容,每天自动发到您的邮箱中, 请点这里
选择器
学习目的 熟练使用 css 选择器
css1 中的选择器
E #myid id选择器
E .warning 类选择器
E F 包含选择器
E:link 定义超链接未被访问
E:visited 定义超链接已经被访问
E:actice 匹配被激活的元素
E:hover 鼠标经过的元素
E:focus 获取焦点
E::first-line 元素第一行
E::first-letter 元素第一个字符
css2
* 通配选择文档中所有元素
E[foo] 包含foo属性的元素
E[foo="bar"] 包含属性foo值为bar的元素
CSS3 中的选择器可替代 了解即可
E[foo~="bar"] 含有属性foo值包括bar的元素例如 <a foo="bar bar1 bar2">link</a>
E[foo|="en"] 属性值是一个“-”分割的 比如 en-us
E:first-child 父元素的第一个子元素
E:lang(fr) 匹配属性,元素显示内容为语言为 fr
E::before 在元素前面插入内容
E::after 在元素后面插入内容
E>F 子包含
E+E 相邻兄弟选择器 后面的兄弟
css3
E[foo^="bar"] 属性foo的值开头是bar
E[foo$="bar"] 属性foo的值得结尾是bar
E[foo*="bar"] 属性foo的值包含bar <a foo="abc_bar_as">link</a>
结构类选择器
E:root 属性文档所在的根元素
E:nth-child(n) E元素第n个位置的子元素 n可以是 (1,2,3) 关键字(odd,even) 公式(2n,2n+3) 起始值为1
E:nth-last-child(n) 与上面的使用方法一样 倒数的第N个位置的子元素
E:nth-of-type(n) 匹配父元素中与E相同的元素中的第n个元素
E:nth-last-of-type(n) 匹配父元素中与E相同的倒数第n个元素
E:last-child 选择位于其父元素的最后一个位置,且匹配E的子元素
E:first-of-type 选择在其父元素中匹配E的第一个同类型的子元素
E:last-of-type 选择在其父元素中匹配E的最后一个同类型的子元素
E:only-child 选择其父元素只包含一个子元素,且该子元素匹配E
E:only-of-type 选择其父元素只包含一个同类型的子元素,且该子元素匹配E
E:empty 选择匹配E的元素,且该元素不包含子节点,文本也是节点
E~F 通用兄弟选择器
E:not(s) 否定伪类选择器
蓝蓝设计( www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 、平面设计服务。
如果您想订阅本博客内容,每天自动发到您的邮箱中, 请点这里
前言
对比网上的例子
<a href="#" id="username" data-type="text" data-pk="1">awesome</a> <script> $(function(){ $('#username').editable({
url: '/post',
title: 'Enter username' });
}); </script>
$('#db_dependences').bootstrapTable({
method:'POST',
dataType:'json',
contentType: "application/x-www-form-urlencoded",
cache: false,
striped: true, //是否显示行间隔色 sidePagination: "client", //分页方式:client客户端分页,server服务端分页(*) showColumns:true,
pagination:true,
minimumCountColumns:2,
pageNumber:1, //初始化加载第一页,默认第一页 pageSize: 10, //每页的记录行数(*) pageList: [10, 15, 20, 25], //可供选择的每页的行数(*) uniqueId: "id", //每一行的唯一标识,一般为主键列 showExport: true,
exportDataType: 'all',
exportTypes:[ 'csv', 'txt', 'sql', 'doc', 'excel', 'xlsx', 'pdf'], //导出文件类型 onEditableSave: function (field, row, oldValue, $el) { $.ajax({
success: function (data, status) { if (status == "success") {
alert("编辑成功");
}
},
error: function () { alert("Error");
},
complete: function () { }
});
},
data: [{
id: 1,
name: '张三',
sex: '男',
time: '2017-08-09' }, {
id: 2,
name: '王五',
sex: '女',
time: '2017-08-09' }, {
id: 3,
name: '李四',
sex: '男',
time: '2017-08-09' }, {
id: 4,
name: '杨朝来',
sex: '男',
time: '2017-08-09' }, {
id: 5,
name: '蒋平',
sex: '男',
time: '2017-08-09' }, {
id: 6,
name: '唐灿华',
sex: '男',
time: '2017-08-09' }],
columns: [{
field: 'id',
title: '序号' }, {
field: 'name',
title: '姓名',
editable: {
type: 'text',
validate: function (value) { if ($.trim(value) == '') { return '姓名不能为空!';
}
}
}
}, {
field: 'sex',
title: '性别',
editable: {
type: 'select',
pk: 1,
source: [
{value: 1, text: '男'},
{value: 2, text: '女'},
]
}
}, {
field: 'time',
title: '时间',
editable: {
type: 'date',
format: 'yyyy-mm-dd',
viewformat: 'yyyy-mm-dd',
datepicker: {
weekStart: 1 }
}
}]
});
结果图如下:
由于开源,很快就找到原因,由于formatter我们没有写这个function导致调用的默认的formatter,默认的没有把表格的值传入html中,bootstrap-table-editable.js源码如下,初始定义_dont_edit_formatter为false,我们没有实现noeditFormatter的function就会执行第二个if语句,其中的标签中没有对内容赋值,导致最后显示结果为它默认的Empty:
column.formatter = function(value, row, index) { var result = column._formatter ? column._formatter(value, row, index) : value;
$.each(column, processDataOptions);
$.each(editableOptions, function(key, value) {
editableDataMarkup.push(' ' + key + '="' + value + '"');
}); var _dont_edit_formatter = false; if (column.editable.hasOwnProperty('noeditFormatter')) {
_dont_edit_formatter = column.editable.noeditFormatter(value, row, index);
} if (_dont_edit_formatter === false) { return ['<a href="javascript:void(0)"', ' data-name="' + column.field + '"', ' data-pk="' + row[that.options.idField] + '"', ' data-value="' + result + '"',
editableDataMarkup.join(''), '>' + '</a>' ].join('');
} else { return _dont_edit_formatter;
}
};
由于要实现多样式,则把上面的代码改变,并在使用的时候实现noeditFormatter:function(value){…}就是了。将上面的代码改为如下(此为我自己改的,你可以根据自己的需要做修改):
column.formatter = function(value, row, index) { var result = column._formatter ? column._formatter(value, row, index) : value;
$.each(column, processDataOptions);
$.each(editableOptions, function(key, value) {
editableDataMarkup.push(' ' + key + '="' + value + '"');
}); var _dont_edit_formatter = false; if (column.editable.hasOwnProperty('noeditFormatter')) { var process = column.editable.noeditFormatter(value, row, index); if(!process.hasOwnProperty('class')){
process.class = '';
} if(!process.hasOwnProperty('style')){
process.style = '';
}
_dont_edit_formatter = ['<a href="javascript:void(0)"', ' data-name="'+process.filed+'"', ' data-pk="1"', ' data-value="' + process.value + '"', ' class="'+process.class+'" style="'+process.style+'"', '>' + process.value + '</a>' ].join('');
} if (_dont_edit_formatter === false) { return ['<a href="javascript:void(0)"', ' data-name="' + column.field + '"', ' data-pk="' + row[that.options.idField] + '"', ' data-value="' + result + '"',
editableDataMarkup.join(''), '>' + value + '</a>' ].join('');
} else { return _dont_edit_formatter;
}
};
结果如下:
然后是bootstrap table的使用js文件,在其中实现noeditFormatter函数。返回的result必须包含filed和value,class和style可以不需要,class可以额外用其它插件之类,比如badge,style是增加样式(背景,颜色,字体等)。
$('#db_dependences').bootstrapTable({
method:'POST',
dataType:'json',
contentType: "application/x-www-form-urlencoded",
cache: false,
striped: true, //是否显示行间隔色 sidePagination: "client", //分页方式:client客户端分页,server服务端分页(*) showColumns:true,
pagination:true,
minimumCountColumns:2,
pageNumber:1, //初始化加载第一页,默认第一页 pageSize: 10, //每页的记录行数(*) pageList: [10, 15, 20, 25], //可供选择的每页的行数(*) uniqueId: "id", //每一行的唯一标识,一般为主键列 showExport: true,
exportDataType: 'all',
exportTypes:[ 'csv', 'txt', 'sql', 'doc', 'excel', 'xlsx', 'pdf'], //导出文件类型 onEditableSave: function (field, row, oldValue, $el) { $.ajax({
success: function (data, status) { if (status == "success") {
alert("编辑成功");
}
},
error: function () { alert("Error");
},
complete: function () { }
});
}, // onEditableHidden: function(field, row, $el, reason) { // 当编辑状态被隐藏时触发 // if(reason === 'save') { // var $td = $el.closest('tr').children(); // // $td.eq(-1).html((row.price*row.number).toFixed(2)); // // $el.closest('tr').next().find('.editable').editable('show'); //编辑状态向下一行移动 // } else if(reason === 'nochange') { // $el.closest('tr').next().find('.editable').editable('show'); // } // }, data: [{
id: 1,
name: '张三',
sex: '男',
time: '2017-08-09' }, {
id: 2,
name: '王五',
sex: '女',
time: '2017-08-09' }, {
id: 3,
name: '李四',
sex: '男',
time: '2017-08-09' }, {
id: 4,
name: '杨朝来',
sex: '男',
time: '2017-08-09' }, {
id: 5,
name: '蒋平',
sex: '男',
time: '2017-08-09' }, {
id: 6,
name: '唐灿华',
sex: '男',
time: '2017-08-09' }, {
id: 7,
name: '马达',
sex: '男',
time: '2017-08-09' }, {
id: 8,
name: '赵小雪',
sex: '女',
time: '2017-08-09' }, {
id: 9,
name: '薛文泉',
sex: '男',
time: '2017-08-09' }, {
id: 10,
name: '丁建',
sex: '男',
time: '2017-08-09' }, {
id: 11,
name: '王丽',
sex: '女',
time: '2017-08-09' }],
columns: [{
field: 'id',
title: '序号' }, {
field: 'name',
title: '姓名',
editable: {
type: 'text',
validate: function (value) { if ($.trim(value) == '') { return '姓名不能为空!';
}
}
}
}, {
field: 'sex',
title: '性别',
editable: {
type: 'select',
pk: 1,
source: [
{value: 1, text: '男'},
{value: 2, text: '女'},
],
noeditFormatter: function (value,row,index) { var result={filed:"sex",value:value,class:"badge",style:"background:#333;padding:5px 10px;"}; return result;
}
}
}, {
field: 'time',
title: '时间',
editable: {
type: 'date',
format: 'yyyy-mm-dd',
viewformat: 'yyyy-mm-dd',
datepicker: {
weekStart: 1 },
noeditFormatter: function (value,row,index) { var result={filed:"time",value:value,class:"badge",style:"background:#333;padding:5px 10px;"}; return result;
}
}
}]
});
关于bootstrap table的导出及使用可以看我另外一篇博客。
下载和引用
下载x-editable,并如下引用。
<link href="js/bootstrap_above/x-editable-develop/dist/bootstrap-editable/css/bootstrap-editable.css" rel="stylesheet"> <script src="js/bootstrap_above/x-editable-develop/dist/bootstrap-editable/js/bootstrap-editable.js"></script> <script src="js/bootstrap_above/bootstrap-table-develop/dist/extensions/editable/bootstrap-table-editable.js"></script>
然后讲上诉的一些文件修改添加,就完成了。
另外项目的结果展示
其中的样式都是自行在x-editable的基础上添加的。如配置出问题,以下是源码链接。
蓝蓝设计( www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 、平面设计服务。
如果您想订阅本博客内容,每天自动发到您的邮箱中, 请点这里
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>表单标签及属性介绍</title>
</head>
<body>
<!--form:表单标签,在html页面创建一个表单(浏览器上不显示),若要提交数据到服务器则负责收集数据的标签要放到form内 ;-->
<!--action:(确定表单提交的路径);-->
<!--method提交方式:get(默认值)有内容 ,post没有-->
<form action="#" method="get">
<!--input:输入域标签,获取用户输入信息;-->
<!--type值不同收集方式不同:hidden(隐藏字段,数据会发送到服务器但浏览器不显示),text(文本框),password(密码框),radio(单选框),checkbox(复选框),
file(文件上传组件),submit(提交按钮),button(普通按钮),reset(重置按钮);-->
<!--name:元素名(表单数据需提交到服务器必提供name属性值),服务器通过属性值获取提交数据;-->
<!--readonly:只读-->
<!--value:设置input默认值。submit和reset为按键上显示数据-->
<!--size:大小-->
<!--maxlength:允许输入的最大长度-->
隐藏字段:<input type="hidden" name="id" value=""/><br/>
用户名:<input type="text" name="username" readonly="readonly" value="zhangsan" size="40px" maxlength="20"/><br/>
密码:<input type="password" name="password"/><br/>
确认密码:<input type="password" name="repassword"/><br/>
性别:<input type="radio" name="sex" value="man"/>男
<input type="radio" name="sex" value="woman"/>女<br/>
爱好:<input type="checkbox" name="hobby" value="钓鱼"/>钓鱼
<input type="checkbox" name="hobby" value="打电动"/>打电动
<!--checked:单选或复选框默认勾选-->
<input type="checkbox" name="hobby" value="画画" checked="checked"/>画画<br/>
头像:<input type="file" /><br/>
<!--select:下拉列表标签-->
籍贯:<select name="province">
<!--option:子标签,下拉列表中的一个选项-->
<option>---请选择---</option>
<!--value:发送得服务器的选项值-->
<option value="北京">北京</option>
<option value="上海">上海</option>
<!--selected:勾选当前列表项-->
<option value="广州" selected="selected">广州</option>
</select><br/>
自我介绍:
<!--textarea:文本域-->
<textarea>
</textarea><br/>
提交按钮:<input type="submit" value="注册"/><br/>
普通按钮:<input type="button" value="普通按钮"><br/>
重置按钮:<input type="reset"/>
</form>
</body>
</html>
蓝蓝设计( www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 、平面设计服务。
蓝蓝设计的小编 http://www.lanlanwork.com