Java8 使用 stream().filter()过滤List对象(查找符合条件的对象集合)
内容简介 本文主要说明在Java8及以上版本中,使用stream().filter()来过滤一个List对象,查找符合条件的对象集合。 List对象类(StudentInfo)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 |
public class StudentInfo implements Comparable<StudentInfo> { //名称 private String name; //性别 true男 false女 private Boolean gender; //年龄 private Integer age; //身高 private Double height; //出生日期 private LocalDate birthday; public StudentInfo(String name, Boolean gender, Integer age, Double height, LocalDate birthday){ this.name = name; this.gender = gender; this.age = age; this.height = height; this.birthday = birthday; } public String toString(){ String info = String.format("%s\t\t%s\t\t%s\t\t\t%s\t\t%s",this.name,this.gender.toString(),this.age.toString(),this.height.toString(),birthday.toString()); return info; } public static void printStudents(List<StudentInfo> studentInfos){ System.out.println("[姓名]\t\t[性别]\t\t[年龄]\t\t[身高]\t\t[生日]"); System.out.println("----------------------------------------------------------"); studentInfos.forEach(s->System.out.println(s.toString())); System.out.println(" "); } @Override public int compareTo(StudentInfo ob) { return this.age.compareTo(ob.getAge()); //return 1; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Boolean getGender() { return gender; } public void setGender(Boolean gender) { this.gender = gender; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } public Double getHeight() { return height; } public void setHeight(Double height) { this.height = height; } public LocalDate getBirthday() { return birthday; } public void setBirthday(LocalDate birthday) { this.birthday = birthday; } } |
测试数据
1 2 3 4 5 6 |
//测试数据,请不要纠结数据的严谨性 List<StudentInfo> studentList = new ArrayList<>(); studentList.add(new StudentInfo("李小明",true,18,1.76,LocalDate.of(2001,3,23))); studentList.add(new StudentInfo("张小丽",false,18,1.61,LocalDate.of(2001,6,3))); studentList.add(new StudentInfo("王大朋",true,19,1.82,LocalDate.of(2000,3,11))); studentList.add(new StudentInfo("陈小跑",false,17,1.67,LocalDate.of(2002,10,18))); |
输出Students列表
1 2 |
//输出List StudentInfo.printStudents(studentList); |
输出结果如下图: 使用filter()过滤List
1 2 3 4 |
//查找身高在1.8米及以上的男生 List<StudentInfo> boys = studentList.stream().filter(s->s.getGender() && s.getHeight() >= 1.8).collect(Collectors.toList()); //输出查找结果 StudentInfo.printStudents(boys); |
结果如下图: from:https://www.cnblogs.com/codecat/p/10912454.html
View Detailsjava8 .stream().map().collect()用法
API: https://www.runoob.com/java/java8-streams.html
1 2 3 4 |
mylist.stream() .map(myfunction->{ return item; }).collect(Collectors.toList()); |
说明: steam():把一个源数据,可以是集合,数组,I/O channel, 产生器generator 等,转化成流。 forEach():迭代流中的每个数据。以下代码片段使用 forEach 输出了10个随机数.
1 2 |
Random random = new Random(); random.ints().limit(10).forEach(System.out::println); |
map():用于映射每个元素到对应的结果。以下代码片段使用 map 输出了元素对应的平方数:
1 2 3 |
List<Integer> numbers = Arrays.asList(3, 2, 2, 3, 7, 3, 5); // 获取对应的平方数 List<Integer> squaresList = numbers.stream().map( i -> i*i).distinct().collect(Collectors.toList()); |
filter():filter 方法用于通过设置的条件过滤出元素。以下代码片段使用 filter 方法过滤出空字符串:
1 2 3 4 5 6 7 8 |
List<String>strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl"); // 获取空字符串的数量 int count = strings.stream().filter(string -> string.isEmpty()).count(); limit limit 方法用于获取指定数量的流。 以下代码片段使用 limit 方法打印出 10 条数据: Random random = new Random(); random.ints().limit(10).forEach(System.out::println); |
sorted(): 用于对流进行排序。以下代码片段使用 sorted 方法对输出的 10 个随机数进行排序:
1 2 3 4 5 6 7 8 9 |
Random random = new Random(); random.ints().limit(10).sorted().forEach(System.out::println); 并行(parallel)程序 parallelStream 是流并行处理程序的代替方法。以下实例我们使用 parallelStream 来输出空字符串的数量: List<String> strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl"); // 获取空字符串的数量 int count = strings.parallelStream().filter(string -> string.isEmpty()).count(); 我们可以很容易的在顺序运行和并行直接切换。 |
Collectors(): 类实现了很多归约操作,例如将流转换成集合和聚合元素。Collectors 可用于返回列表或字符串:
1 2 3 4 5 6 |
List<String>strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl"); List<String> filtered = strings.stream().filter(string -> !string.isEmpty()).collect(Collectors.toList()); System.out.println("筛选列表: " + filtered); String mergedString = strings.stream().filter(string -> !string.isEmpty()).collect(Collectors.joining(", ")); System.out.println("合并字符串: " + mergedString); |
from:https://blog.csdn.net/shine_guo_star/article/details/94383319
View Detailsjdk8的特性stream().map()
转: https://blog.csdn.net/sanchan/article/details/70753645 java8的optional的使用: http://www.jdon.com/idea/java/using-optional-effectively-in-java-8.html http://www.runoob.com/java/java8-optional-class.html Optional 类是一个可以为null的容器对象。如果值存在则isPresent()方法会返回true,调用get()方法会返回该对象。 Optional 是个容器:它可以保存类型T的值,或者仅仅保存null。Optional提供很多有用的方法,这样我们就不用显式进行空值检测。 Optional 类的引入很好的解决空指针异常。 类声明 以下是一个 java.util.Optional<T> 类的声明: public final class Optional<T> extends Object
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 |
在Java 8中stream().map(),您可以将对象转换为其他对象。查看以下示例: 1.大写字符串列表 1.1简单的Java示例将Strings列表转换为大写。 TestJava8.java package com.mkyong.java8; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.stream.Collectors; public class TestJava8 { public static void main(String[] args) { List<String> alpha = Arrays.asList("a", "b", "c", "d"); //Before Java8 List<String> alphaUpper = new ArrayList<>(); for (String s : alpha) { alphaUpper.add(s.toUpperCase()); } System.out.println(alpha); //[a, b, c, d] System.out.println(alphaUpper); //[A, B, C, D] // Java 8 List<String> collect = alpha.stream().map(String::toUpperCase).collect(Collectors.toList()); System.out.println(collect); //[A, B, C, D] // Extra, streams apply to any data type. List<Integer> num = Arrays.asList(1,2,3,4,5); List<Integer> collect1 = num.stream().map(n -> n * 2).collect(Collectors.toList()); System.out.println(collect1); //[2, 4, 6, 8, 10] } } 2.对象列表 - >字符串列表 2.1 name从staff对象列表中获取所有值。 Staff.java package com.mkyong.java8; import java.math.BigDecimal; public class Staff { private String name; private int age; private BigDecimal salary; //... } TestJava8.java package com.mkyong.java8; import java.math.BigDecimal; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.stream.Collectors; public class TestJava8 { public static void main(String[] args) { List<Staff> staff = Arrays.asList( new Staff("mkyong", 30, new BigDecimal(10000)), new Staff("jack", 27, new BigDecimal(20000)), new Staff("lawrence", 33, new BigDecimal(30000)) ); //Before Java 8 List<String> result = new ArrayList<>(); for (Staff x : staff) { result.add(x.getName()); } System.out.println(result); //[mkyong, jack, lawrence] //Java 8 List<String> collect = staff.stream().map(x -> x.getName()).collect(Collectors.toList()); System.out.println(collect); //[mkyong, jack, lawrence] } } 对象列表 - >其他对象列表 3.1此示例说明如何将staff对象列表转换为对象列表StaffPublic。 Staff.java package com.mkyong.java8; import java.math.BigDecimal; public class Staff { private String name; private int age; private BigDecimal salary; //... } StaffPublic.java package com.mkyong.java8; public class StaffPublic { private String name; private int age; private String extra; //... } 3.2 Java 8之前。 BeforeJava8.java package com.mkyong.java8; import java.math.BigDecimal; import java.util.ArrayList; import java.util.Arrays; import java.util.List; public class BeforeJava8 { public static void main(String[] args) { List<Staff> staff = Arrays.asList( new Staff("mkyong", 30, new BigDecimal(10000)), new Staff("jack", 27, new BigDecimal(20000)), new Staff("lawrence", 33, new BigDecimal(30000)) ); List<StaffPublic> result = convertToStaffPublic(staff); System.out.println(result); } private static List<StaffPublic> convertToStaffPublic(List<Staff> staff) { List<StaffPublic> result = new ArrayList<>(); for (Staff temp : staff) { StaffPublic obj = new StaffPublic(); obj.setName(temp.getName()); obj.setAge(temp.getAge()); if ("mkyong".equals(temp.getName())) { obj.setExtra("this field is for mkyong only!"); } result.add(obj); } return result; } } 输出 [ StaffPublic{name='mkyong', age=30, extra='this field is for mkyong only!'}, StaffPublic{name='jack', age=27, extra='null'}, StaffPublic{name='lawrence', age=33, extra='null'} ] 1 2 3 4 5 3.3 Java 8的例子。 NowJava8.java package com.mkyong.java8; package com.hostingcompass.web.java8; import java.math.BigDecimal; import java.util.Arrays; import java.util.List; import java.util.stream.Collectors; public class NowJava8 { public static void main(String[] args) { List<Staff> staff = Arrays.asList( new Staff("mkyong", 30, new BigDecimal(10000)), new Staff("jack", 27, new BigDecimal(20000)), new Staff("lawrence", 33, new BigDecimal(30000)) ); // convert inside the map() method directly. List<StaffPublic> result = staff.stream().map(temp -> { StaffPublic obj = new StaffPublic(); obj.setName(temp.getName()); obj.setAge(temp.getAge()); if ("mkyong".equals(temp.getName())) { obj.setExtra("this field is for mkyong only!"); } return obj; }).collect(Collectors.toList()); System.out.println(result); } } [ StaffPublic{name='mkyong', age=30, extra='this field is for mkyong only!'}, StaffPublic{name='jack', age=27, extra='null'}, StaffPublic{name='lawrence', age=33, extra='null'} ] |
from:https://www.cnblogs.com/fengli9998/p/9002377.html
View DetailsDapperExtensions扩展,一个不再更新的小众类库的踩坑之路
公司一个项目要从.net framework平台转成.net core平台,都是为了跨平台啊。 老的项目中用了个小众的类库:DapperExtensions。 有个同事直接nuget安装了该类库的.net core版本:DapperExtensions.NetCore,然后一直报错;于是向我求助。 报错代码如下图: 报错信息: P.S 同事用的是异步调用,同步调用是没问题的。 由于此类库不再更新,官网也没有了……也找不到文档; 在网上很少的资料中,都是些简单的示例,使用的都是同步调用,但同事用的是异步调用。我们一块折腾了半个上午,也没解决。但还不想放弃啊……于是又双叒叕重新撸了n遍,豁然发现:生成的MySQL语句里怎么会有中括号!灯下黑~…… 于是,网上一通搜,终于找到一篇说SQL方言的文档,看了一下DapperExtensions的源码,发现也有设置SQL方言的方法:
1 |
DapperExtensions.DapperExtensions.SqlDialect = new MySqlDialect(); |
运行……还是报错……%~@#¥,没起作用!无奈……拉倒吧,把代码改为同步调用吧。 还是不想放弃,再看一眼吧——竟然发现DapperExtensions的源码中异步方法和同步方法的SQL方言竟然是单独设置的,这类库设计的也没谁了……,于是设置了一下异步的SQL方言为MySQL,终于解决了。代码如下:
1 |
DapperExtensions.DapperAsyncExtensions.SqlDialect = new MySqlDialect(); |
总结: 不要使用小众类库,尤其是个人开发的。因为出了问题太难解决了。 解决问题要细心,更要有耐心;放空思想,从头多撸几遍。 小众类库的代码设计考虑不周: a. 比如说,代码已经写为new MySqlConnection(ConnString),SQL方言就应该自动设置为MySQL了。 b. 另一个,对于SQL方言,设置一次就行了,不应该设计成异步要单独设置。 解决过程实属不易,希望能帮助大家,谢谢~
View DetailsSQL注入测试
简介 SQL 注入是一种专门针对SQL语句的攻击方式。通过把SQL命令插入到web表单提交、输入域名或者页面请求的查询字符串中,利用现有的程序,来非法获取后台的数据库中的信息。在web的测试中涉及到的会比较多些。 注入原理 存在注入的原因是后台在编写程序时,没有对用户输入的数据做过滤。 例: 1、用户在某个输入框提交的参数是123。 浏览器提交的URL为: http://www.xxx.com/index.php?id=123 服务器后台执行SQL语句:select * from table1 where id = 123 此时是没有任何影响的。 2、 如果用户提交的参数是 123;drop table 服务器后台执行SQL语句: select * from table1 where id =123 ; drop table 相当于后台执行了两条SQL语句,查表,并且把table删除, 从而导致了SQL注入 检测注入的方法 目前主要有两种检测方式: 一、手工注入检测流程: 1. 判断是否存在注入点 www.abc.com/index.php?id=2 www.abc.com/index.php?id=2 and 1=1 www.abc.com/index.php?id=2 and 1=2 第2条返回正常, 第1,3条返回不正常说明id参数存在注入漏洞 2. 判定是否存在admin表 www.abc.com/index.php?id=2 and exists(select * from admin) 返回正常,存在admin表 3. 猜admin表中的字段名 www.abc.com/index.php?id=2 and exists(select username from admin) 返回正常 表示admin表存在username字段 4. 检测其他sql操作 二、工具检测: sqlmap: sqlmap是一个开源的渗透测试工具,可以用来进行自动化检测,利用SQL注入漏洞,获取数据库服务器的权限。 1. 下载地址 https://github.com/sqlmapproject/sqlmap.git 2. 常用命令 测试 以一个sqlmap检测URL为例: […]
View DetailsVue 中 强制组件重新渲染的正确方法
有时候,依赖 Vue 响应方式来更新数据是不够的,相反,我们需要手动重新渲染组件来更新数据。或者,我们可能只想抛开当前的DOM,重新开始。那么,如何让Vue以正确的方式重新呈现组件呢? 强制 Vue 重新渲染组件的最佳方法是在组件上设置:key。 当我们需要重新渲染组件时,只需更 key 的值,Vue 就会重新渲染组件。 这是一个非常简单的解决方案。 当然,你可能会对其他方式会更感兴趣: 简单粗暴的方式:重新加载整个页面 不妥的方式:使用 v-if 较好的方法:使用Vue的内置forceUpdate方法 最好的方法:在组件上进行 key 更改 简单粗暴的方式:重新加载整个页面 这相当于每次你想关闭应用程序时都要重新启动你的电脑。 这种方式或许有用,但这是一个非常糟糕的解决方案,不要这样做,我们来看看更好的方法。 不妥的方式:使用 v-if v-if指令,该指令仅在组件为true时才渲染。 如果为false,则该组件在DOM中不存在。 来看看,v-if 是怎么工作的,在template中,添加v-if指令:
1 2 3 |
<template> <my-component v-if="renderComponent" /> </template> |
在script 中,使用nextTick的方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
<script> export default { data() { return { renderComponent: true, }; }, methods: { forceRerender() { // 从 DOM 中删除 my-component 组件 this.renderComponent = false; this.$nextTick(() => { // 在 DOM 中添加 my-component 组件 this.renderComponent = true; }); } } }; </script> |
上面的过程大致如下: 刚开始 renderComponent设置为true,因此渲染 my-component 组件 当我们调用forceRerender时,我们立即将renderComponent设置为false 我们停止渲染my-component,因为v-if指令现在计算结果为false 在nextTick方法中将renderComponent设置回true 当v-if指令的计算结果为true时,再次渲染my-component 在这个过程中,有两个部分比较重要 首先,我们必须等到nextTick,否则我们不会看到任何变化。 在Vue中,一个 tick 是一个DOM更新周期。Vue将收集在同一 tick 中进行的所有更新,在 tick 结束时,它将根据这些更新来渲染 DOM 中的内容。如果我们不等到next tick,我们对renderComponent的更新就会自动取消,什么也不会改变。 其次,当我们第二次渲染时,Vue将创建一个全新的组件。 Vue 将销毁第一个,并创建一个新的,这意味着我们的新my-component将像正常情况一样经历其所有生命周期-created,mounted等。 另外,nextTick 可以与 promise 一起使用:
1 2 3 4 5 6 7 8 |
forceRerender() { // 从 DOM 中删除 my-component 组件 this.renderComponent = false; this.$nextTick().then(() => { this.renderComponent = true; }); } |
不过,这并不是一个很好的解决方案,所以,让我们做 Vue 想让我们做的 较好的方法:forceUpdate 方法 这是解决这个问题的两种最佳方法之一,这两种方法都得到了Vue的官方支持。 通常情况下,Vue 会通过更新视图来响应依赖项中的更改。然而,当我们调用forceUpdate时,也可以强制执行更新,即使所有依赖项实际上都没有改变。 下面是大多数人使用这种方法时所犯的最大错误。 如果 Vue 在事情发生变化时自动更新,为什么我们需要强制更新呢? 原因是有时候 Vue 的响应系统会让人感到困惑,我们认为Vue会对某个属性或变量的变化做出响应,但实际上并不是这样。在某些情况下,Vue的响应系统根本检测不到任何变化。 所以就像上一个方法,如果你需要这个来重新渲染你的组件,可能有一个更好的方法。 有两种不同的方法可以在组件实例本身和全局调用forceUpdate:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
// 全局 import Vue from 'vue'; Vue.forceUpdate(); // 使用组件实例 export default { methods: { methodThatForcesUpdate() { // ... this.$forceUpdate(); // ... } } } |
重要提示:这不会更新任何计算属性,调用forceUpdate仅仅强制重新渲染视图。 最好的方法:在组件上进行 key 更改 在许多情况下,我们需要重新渲染组件。 要正确地做到这一点,我们将提供一个key属性,以便 Vue 知道特定的组件与特定的数据片段相关联。如果key保持不变,则不会更改组件,但是如果key发生更改,Vue 就会知道应该删除旧组件并创建新组件。 正是我们需要的! 但是首先,我们需要绕一小段路来理解为什么在Vue中使用key。 为什么我们需要在 Vue 中使用 key 一旦你理解了这一点,那么这是了解如何以正确方式强制重新渲染的很小的一步。 假设我们要渲染具有以下一项或多项内容的组件列表: 有本地的状态 某种初始化过程,通常在created或mounted钩子中 […]
View Detailsgitlab 的 CI/CD 初次尝试
一、前言 ci/cd 持续集成持续交付,开发人员尝尝会遇到一些重复工作,比如一个asp.net的网站代码,写完之后要发布,然后再将发布内容移动到部署的服务器上再进行部署,就算你只改了一个页面上的一个字,也要将之前的发布部署过程重新做一遍。 CI 解决了这个重复性问题,开发人员只需git push 提交代码,剩下的工作交给CI , 做CI工作的有gitlab-ci/cd Jenkins k8s等,中小项目gitlab-ci比较合适,因为它更轻量级一些,本篇仅讨论gitlab的cicd功能。 二、环境 IP 角色 192.168.10.202(ubuntu) gitlab 192.168.10.208(centos) git,docker,gitlab-runner gitlab git docker 三者的安装 略。且本篇是以docker镜像方式部署 上图为gitlab-ci的过程,其实它只是省略了一些我们的手动发布部署过程,将其自动化,但原来的流程还是一个不能少。所以,我们要进行的第一步,就是手动实现一遍流程。 三、手动实现一遍 (gitlab服务器) 创建代码仓库—> (开发PC) git clone —> (开发pc) 修改代码,添加dockerfile —> (开发pc) git push —> (部署服务器) git pull —> (部署服务器) docker build ,docker run 1、创建代码仓库 在创建之前,需要在使用git的机器上设置好ssh,可以参考之前的https://www.cnblogs.com/hallejuayahaha/p/11996332.html 要注意的是,在部署机器上,gitlab-runner安装好后,需要添加一个gitlab-runner的用户,需要添加这个用的ssh,因为在ci自动化后,在部署服务器上的操作都是由这个用户来做的,所以不仅要添加它的ssh,也要docker 免去sudo的指令。 总之就是让gitlab-runner用户,在做部署过程中,不要受到权限的阻碍。 ******docker免去敲sudo******* 在安装完docker之后,也会出现一个docker用户组,将你要免去敲sudo的用户添加进去,就可以了
1 |
sudo usermod -aG docker gitlab-runner |
添加代码仓库 并将一个.netcore项目创建进去 添加dockerfile文件,仅需在项目上右键,docker支持,vs就可以自动添加。然后git push 这样开发pc端的代码就都提交到gitlab服务器上了, 2、部署端git pull ,docker build , docker run 镜像已经成功启动,打开浏览器,输入ip + 暴露出来的端口8090 PS: .NETCORE web中,startup.cs文件中,有 app.UseHsts(); app.UseHttpsRedirection(); 这两行要注释掉,不然网站回一直往https跳转,没法进入http的80端口 整个手动流程成功。 […]
View DetailsMySQL 截取部分日期
使用 DATE_FORMAT(get_date, '%Y-%m-%d') 函数截取。 其中:get_date 是需要截取的字段名;’%Y-%m-%d' 是截取后的日期格式。 select date_format('1997-10-04 22:23:00′,’%y %M %b %D %W %a %Y-%m-%d %H:%i:%s %r %T'); 结果:97 October Oct 4th Saturday Sat 1997-10-04 22:23:00 10:23:00 PM 22:23:00 get_date = "2006-12-07" SELECT count(*) FROM t_get_video_temp Where DATE_FORMAT(get_date, '%Y-%m-%d')=’2006-12-07′; SELECT count(*) FROM t_get_video_temp Where get_date like '2006%-07%'; from:https://blog.csdn.net/hlbt0112/article/details/50600191/
View Detailswebview调用ios或者安卓的方法(内嵌h5页面调用app原生方法)
1.配合使用调用app原生的方法(h5页面不需要回调和数据) 实例1
1 2 3 4 5 6 7 8 9 |
// 通知客户端,token失效 callTokenLostToApp(){ let boswer = vm.config.getBrowser() if(boswer == 'isiOS'){ window.webkit.messageHandlers.tokenExpiredTransmit.postMessage(1); }else if(boswer == 'isAndroid'){ window.tokenExpiredTransmit.jsMethod(1) } }, |
实例2
1 2 3 4 5 6 7 8 9 |
// 关闭页面 closePageApp(cb){ let boswer = vm.config.getBrowser() // IOS 关闭页面 if(boswer == 'isiOS'){ // 这段代码是固定的,必须要放到js中 window.webkit.messageHandlers.closePage.postMessage(1); // 安卓关闭页面 }else if(boswer == 'isAndroid'){ window.closePage.jsMethod(1) } }, |
2.配合使用调用app原生的方法(h5页面需要回调和数据) // 从App获取UUID(手机唯一标识)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
// 从App获取UUID(手机唯一标识) getSystemInfoFromApp(cb){ let boswer = vm.config.getBrowser() // IOS 获取UUID if(boswer == 'isiOS'){ // 这段代码是固定的,必须要放到js中 function setupWebViewJavascriptBridge(callback) { if (window.WebViewJavascriptBridge) { return callback(WebViewJavascriptBridge); } if (window.WVJBCallbacks) { return window.WVJBCallbacks.push(callback); } window.WVJBCallbacks = [callback]; var WVJBIframe = document.createElement('iframe'); WVJBIframe.style.display = 'none'; WVJBIframe.src = 'wvjbscheme://__BRIDGE_LOADED__'; document.documentElement.appendChild(WVJBIframe); setTimeout(function() { document.documentElement.removeChild(WVJBIframe) }, 0) } /*与OC交互的所有JS方法都要放在此处注册,才能调用通过JS调用OC或者让OC调用这里的JS*/ setupWebViewJavascriptBridge(function(bridge) { /*JS给ObjC提供公开的API,ObjC端通过注册,就可以在JS端调用此API时,得到回调。ObjC端可以在处理完成后,反馈给JS,这样写就是在载入页面完成时就先调用*/ bridge.callHandler('getSystemInfoFromApp', function(responseData) { if(cb && typeof cb == 'function'){ cb(responseData) }else{ return responseData } }) }) // 安卓获取UUID }else if(boswer == 'isAndroid'){ let systemInfo = window.AndroidWebView.getSystemInfoFromApp(); if(cb && typeof cb == 'function'){ cb(systemInfo) }else{ return systemInfo } } }, |
标红字段为调用的app端定义的方法名,需要app端定义方法配合 from:https://www.cnblogs.com/wendyAndJken/p/9318501.html
View Details精选!18个 VS Code 高效插件,献给需要的前端程序猿/媛
先写前面 俗话说 欲先善其事必先利器,作为一个21新世纪的打工人,怎么可以没有一个趁手的编辑器工具呢。今天的主角就是 VS Code ,一个炒鸡强大的编辑器,我们先来介绍一下这个编辑器。 VS Code 全称 Visual Studio Code 是由微软开发的一款免费、跨平台的轻量级代码编辑器。以功能强大、提示友好、不错的性能和颜值俘获了大量开发者的青睐,对 JavaScript 和 NodeJS 的支持非常好,自带很多功能,例如代码格式化,代码智能提示补全等。 再强大的IDE那也不可能面面俱到什么功能都塞进去,那样只会导致IDE本身太臃肿。功能嘛,按需索取,所以,vscode的很多强大功能都是基于插件实现的,IDE只提供一个最基本的框子和最基本功能,由插件来丰富和扩展它的功能。 美化插件 一个美美的编辑器,在我们的开发过程中是非常友好的,所以我们先来介绍一下用于美化的插件 1. Material Theme 插件 Material Theme 插件是一款用于美化主题的图标的插件,该插件包含两个子插件,分别是 Community Material Theme 该插件用于美化主题,还有一个 Material Theme Icons 用于美化图标的。 image-20201116212608537 2. VSCode Great Icons 插件 VSCode Great Icons 插件是 VS Code 图标插件,可以控制 VS Code 中的文件管理的树目录显示图标。不过如果安装上面那个插件这个插件也就不需要了。 image-20201116213037910 代码高亮插件 1. Color Highlight 插件 Color Highlight 插件是 VS Code 中的颜色高亮插件,可以在编辑器中看出其背景颜色。 image-20201116213858966 2. vscode-pigments 插件 该插件也是一款颜色高亮插件,同上一个插件类似,是我现在使用的一个颜色高亮的插件 image-20201116214057772 3. Bracket Pair Colorizer 插件 为不同的括号拥有不同的颜色,可以使嵌套结构表现特别明显,这个插件是我非常喜欢的一个插件,给我安排它。 image-20201116225424675 高效插件 1. Search node_modules 插件 Search node_modules 插件是一款高效的查找插件,当我们的文件太多时,需要找到某个定义的方法时,可以通过该插件在当前文件夹进行搜索内用 image-20201116214435807 2. Path Intellisense […]
View Details