weex早期在Android上使用的是V8,但经过测试,JavaScriptCore的性能比V8的性能更好,所以便用JavaScriptCore全面替代了V8
主分支默认使用由 UC 提供的 V8 引擎,默认只提供 armeabi-v7a, x86 两个版本的引擎。
系统只能是ubuntu 16.04,因为编译的时候需要gcc-4.7的头文件。
weex早期在Android上使用的是V8,但经过测试,JavaScriptCore的性能比V8的性能更好,所以便用JavaScriptCore全面替代了V8
主分支默认使用由 UC 提供的 V8 引擎,默认只提供 armeabi-v7a, x86 两个版本的引擎。
系统只能是ubuntu 16.04,因为编译的时候需要gcc-4.7的头文件。
在项目当中,遇到一个问题。当父页面的某个属性变化时,需要router-view中的页面根据不同的值进行不同的操作。
仔细想一下,其实类似父子组件之间的传值。
实现过程如下:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
<template> <router-view v-on:test="testP" v-bind:msg="msg"></router-view> </template> <script type="text/javascript"> export default { data() { return { msg: "把我带给router-view吧!" } }, methods: { testP: function (data) { // 从router-view返回来的数据 console.log(data) // 打印出来就是 // 把我带给父组件吧!第一次! // 把我带给父组件吧!第二次! } } } </script> |
|
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 |
<template> <div>{{msg}}</div> </template> <script type="text/javascript"> export default { props:['msg'], data() { return {} }, watch: { // 监听父组件的msg的变化 msg: function() { console.log(this.msg) // 打印出来就是 // 把我带给router-view吧! } }, mounted() { // this.init() }, methods: { init() { // 第一次向父组件传值 this.$emit("test", "把我带给父组件吧!第一次!") // 第二次向父组件传值 this.$emit("test", "把我带给父组件吧!第二次!") } } } |
注意:
|
1 |
<router-view v-on:test="testP" v-bind:msg="msg"></router-view> |
v-on 绑定的函数名 test,尽量不要出现大写字母(驼峰命名)(比如 v-on:Aplus_clicked="testP"),否则在某些特殊使用方式的情况下,可能会出现无法触发的问题。
驼峰命名,可能会发生如下报错:
|
1 |
[Vue tip]: Event "aplus_clicked" is emitted in component <Anonymous> but the handler is registered for "Aplus_clicked". Note that HTML attributes are case-insensitive and you cannot use v-on to listen to camelCase events when using in-DOM templates. You should probably use "aplus_clicked" instead of "Aplus_clicked". |
The import() operator lets us dynamically load ECMAScript modules. But they can also be used to evaluate JavaScript code (as Andrea Giammarchi recently pointed out to me), as an alternative to eval(). This blog post explains how that works.
eval() does not support export and importA significant limitation of eval() is that it doesn’t support module syntax such as export and import.
If we use import() instead of eval(), we can actually evaluate module code, as we will see later in this blog post.
In the future, we may get Realms which are, roughly, a more powerful eval() with support for modules.
import()Let’s start by evaluating a console.log() via import():
|
1 2 3 4 5 6 7 8 |
const js = `console.log('Hello everyone!');`; const encodedJs = encodeURIComponent(js); const dataUri = 'data:text/javascript;charset=utf-8,' + encodedJs; import(dataUri); // Output: // 'Hello everyone!' |
What is going on here?
data:. The remainder of the URI encodes the full resource instead pointing to it. In this case, the data URI contains a complete ECMAScript module – whose content type is text/javascript.Warning: This code only works in web browsers. On Node.js, import() does not support data URIs.
The fulfillment value of the Promise returned by import() is a module namespace object. That gives us access to the default export and the named exports of the module. In the following example, we access the default export:
|
1 2 3 4 5 6 7 8 9 10 11 |
const js = `export default 'Returned value'`; const dataUri = 'data:text/javascript;charset=utf-8,' + encodeURIComponent(js); import(dataUri) .then((namespaceObject) => { assert.equal(namespaceObject.default, 'Returned value'); }) .catch((err) => { console.log(err.message); // "Importing a module script failed." // apply some logic, e.g. show a feedback for the user }); |
With an appropriate function esm (whose implementation we’ll see later), we can rewrite the previous example and create the data URI via a tagged template:
|
1 2 3 4 5 6 7 8 9 |
const dataUri = esm`export default 'Returned value'`; import(dataUri) .then((namespaceObject) => { assert.equal(namespaceObject.default, 'Returned value'); }) .catch((err) => { console.log(err.message); // "Importing a module script failed." // apply some logic, e.g. show a feedback for the user }); |
The implementation of esm looks as follows:
|
1 2 3 4 5 6 |
function esm(templateStrings, ...substitutions) { let js = templateStrings.raw[0]; for (let i=0; i<substitutions.length; i++) { js += substitutions[i] + templateStrings.raw[i+1]; } return 'da |
For the encoding, we have switched from charset=utf-8 to base64. Compare:
'a' < 'b'data:text/javascript;charset=utf-8,'a'%20%3C%20'b'data:text/javascript;base64,J2EnIDwgJ2InEach of the two ways of encoding has different pros and cons:
charset=utf-8 (percent-encoding):
base64:
btoa() is a global utility function that encodes a string via base 64. Caveats:
With tagged templates, we can nest data URIs and encode a module m2 that imports another module m1:
|
1 2 3 4 5 6 7 8 |
const m1 = esm`export function f() { return 'Hello!' }`; const m2 = esm`import {f} from '${m1}'; export default f()+f();`; import(m2) .then(ns => assert.equal(ns.default, 'Hello!Hello!')) .catch((err) => { console.log(err.message); // "Importing a module script failed." // apply some logic, e.g. show a feedback for the user }); |
import() in “JavaScript for impatient programmers”Virtual Box supports up to 256 MB of video RAM. This can not be set using the slider of the Virtual Box Manager.
To make full use of all supported memory we can issue the following command in a terminal:
|
1 |
$ VBoxManage modifyvm "Name of VM" --vram 256 |
Before we change settings such as the video RAM a pre-existing virtual machine has to be shut down.
Note that for 3D video hardware acceleration from the guest addition’s video driver the physical RAM of the host graphics card will be passed through. The video RAM settings of the virtual machine will not affect this.
|
1 2 3 4 5 |
if((navigator.userAgent.match(/(phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|Windows Phone)/i))) { window.location.href = ""; //手机 } else { window.location.href = ""; //电脑 } |
也可以执行其他操作:
|
1 2 3 4 5 |
if((navigator.userAgent.match(/(phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|Windows Phone)/i))) { alert('您正在通过手机访问'); } else { alert("您在PC端访问"); } |
JS判断客户端是否是iOS或者Android手机移动端:
通过判断浏览器的 userAgent,用正则来判断手机是否是ios和Android客户端。代码如下:
|
1 2 3 4 5 6 7 |
<script type="text/javascript"> var u = navigator.userAgent; var isAndroid = u.indexOf('Android') > -1 || u.indexOf('Adr') > -1; //android终端 var isiOS = !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/); //ios终端 alert('是否是Android:'+isAndroid); alert('是否是iOS:'+isiOS); </script> |
下面一个比较全面的浏览器检查函数,提供更多的检查内容,你可以检查是否是移动端(Mobile)、ipad、iphone、微信、QQ等。
第一种:
|
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 |
<script type="text/javascript"> //判断访问终端 var browser={ versions:function(){ var u = navigator.userAgent, app = navigator.appVersion; return { trident: u.indexOf('Trident') > -1, //IE内核 presto: u.indexOf('Presto') > -1, //opera内核 webKit: u.indexOf('AppleWebKit') > -1, //苹果、谷歌内核 gecko: u.indexOf('Gecko') > -1 && u.indexOf('KHTML') == -1,//火狐内核 mobile: !!u.match(/AppleWebKit.*Mobile.*/), //是否为移动终端 ios: !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/), //ios终端 android: u.indexOf('Android') > -1 || u.indexOf('Adr') > -1, //android终端 iPhone: u.indexOf('iPhone') > -1 , //是否为iPhone或者QQHD浏览器 iPad: u.indexOf('iPad') > -1, //是否iPad webApp: u.indexOf('Safari') == -1, //是否web应该程序,没有头部与底部 weixin: u.indexOf('MicroMessenger') > -1, //是否微信 (2015-01-22新增) qq: u.match(/\sQQ/i) == " qq" //是否QQ }; }(), language:(navigator.browserLanguage || navigator.language).toLowerCase() } //使用方法: //判断是否IE内核 if(browser.versions.trident){ alert("is IE"); } //判断是否webKit内核 if(browser.versions.webKit){ alert("is webKit"); } //判断是否移动端 if(browser.versions.mobile||browser.versions.android||browser.versions.ios){ alert("移动端"); } </script> |
检测浏览器语言
|
1 2 3 4 5 |
currentLang = navigator.language; //判断除IE外其他浏览器使用语言 if(!currentLang){//判断IE浏览器使用语言 currentLang = navigator.browserLanguage; } alert(currentLang); |
第二种:
|
1 2 3 4 5 6 7 8 9 |
if (/(iPhone|iPad|iPod|iOS)/i.test(navigator.userAgent)) { //alert(navigator.userAgent); window.location.href ="iPhone.html"; } else if (/(Android)/i.test(navigator.userAgent)) { //alert(navigator.userAgent); window.location.href ="Android.html"; } else { window.location.href ="pc.html"; }; |
也可以通过这样来适配,然后直接转跳到移动端页面:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
function mobile_device_detect(url){ var thisOS=navigator.platform; var os=new Array("iPhone","iPod","iPad","android","Nokia","SymbianOS","Symbian","Windows Phone","Phone","Linux armv71","MAUI","UNTRUSTED/1.0","Windows CE","BlackBerry","IEMobile"); for(var i=0;i<os.length;i++){ if(thisOS.match(os[i])){ window.location.href=url; } } if(navigator.platform.indexOf('iPad') != -1){ window.location.href=url; } var check = navigator.appVersion; if( check.match(/linux/i) ){ if(check.match(/mobile/i) || check.match(/X11/i)){ window.location.href=url; } } } |
HTML:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title>dddd</title> <link rel="stylesheet" type="text/css" href="test.css" /> </head> <body class="HolyGrail"> <header>...</header> <div class="HolyGrail-body "> <main class="HolyGrail-content">...</main> <nav class="HolyGrail-nav">...</nav> <aside class="HolyGrail-ads">...</aside> </div> <footer>...</footer> </body> |
CSS:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
.HolyGrail { display: flex; flex-direction: column; background-color: blueviolet; } header, footer { height: 100px; background-color: aquamarine; } body { padding: 0; margin: 0; min-height: 100vh; } .HolyGrail-body { flex: 1; background-color: brown; } |
这里需要注意的是设置body的min-height: 100vh;以及margin: 0;
vm、vh、vmin、vmax是一种视窗单位,也是相对单位。它相对的不是父节点或者页面的根节点。而是由视窗(Viewport)大小来决定的,单位 1,代表类似于 1%。 视窗(Viewport)是你的浏览器实际显示内容的区域—,换句话说是你的不包括工具栏和按钮的网页浏览器。
具体描述如下:
vh和vw相对于视口的高度和宽度, 1vh 等于1/100的视口高度,1vw 等于1/100的视口宽度 比如:浏览器高度900px,宽度为750px, 1 vh = 900px/100 = 9 px,1vw = 750px/100 = 7.5 px, 很容易实现与同屏幕等高的框。
默认的Favicon图标
关闭默认图标
在application.properties中添加:
|
1 |
spring.mvc.favicon.enabled=false |
或者(我这个有效果):
|
1 |
spring.favicon.enabled = false |
效果
具体原因:https://jira.spring.io/browse/SPR-12851
springboot显示的是一片叶子,我们如何使用自己的favicon呢?
1.将favicon.icon放到resources目录下 例如:/public,/static等等
2.完成上面的步骤还不能显示,还需在你的页面的head标签添加代码
|
1 2 3 4 5 6 7 |
<head> <meta charset="UTF-8"> <title>登录</title> <link rel="shortcut icon" th:href="@{/favicon.ico}" type="image/x-icon"/> <link rel="icon" th:href="@{/favicon.ico}" type="image/x-icon"/> <link rel="bookmark" th:href="@{/favicon.ico}" type="image/x-icon"/> </head> |
3.注意我使用的thymeleaf所以是以上代码片段如果你不是请这样添加
|
1 2 3 4 5 6 7 |
<head> <meta charset="UTF-8"> <title>登录</title> <link href="/favicon.ico" rel="shortcut icon" type="image/x-icon"/> <link href="/favicon.ico" rel="icon" type="image/x-icon"/> <link href="/favicon.ico" rel="bookmark" type="image/x-icon"/> </head> |
This page describes how to set up fail2ban with OpenVPN 2.4.7 (tested on ubuntu 20.04)
Create /etc/fail2ban/filter.d/openvpn.conf containing:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
# Fail2Ban filter for selected OpenVPN rejections # # [Definition] # Example messages (other matched messages not seen in the testing server's logs): # Fri Sep 23 11:55:36 2016 TLS Error: incoming packet authentication failed from [AF_INET]59.90.146.160:51223 # Thu Aug 25 09:36:02 2016 117.207.115.143:58922 TLS Error: TLS handshake failed failregex = ^ TLS Error: incoming packet authentication failed from \[AF_INET\]<HOST>:\d+$ ^ <HOST>:\d+ Connection reset, restarting ^ <HOST>:\d+ TLS Auth Error ^ <HOST>:\d+ TLS Error: TLS handshake failed$ ^ <HOST>:\d+ VERIFY ERROR ignoreregex = |
Create /etc/fail2ban/jail.local containing:
|
1 2 3 4 5 6 7 8 9 |
# Fail2Ban configuration fragment for OpenVPN [openvpn] enabled = true port = 1194 protocol = udp filter = openvpn logpath = /var/log/openvpn/openvpn.log maxretry = 3 |
To effect the configuration change:
|
1 |
$ service fail2ban restart |
To test the configuration change, check /var/log/fail2ban.log initially for service start messages and later for WARNING [openvpn] Ban and Unban messages.
Mac经常会产生 .DS_Store 的隐藏文件,虽然在 Mac 上看不到,但是有时用了人家的 U 盘或把 U 盘拿到 Windows 系统上用,就会看到。
.DS_Store 是 Mac OS 保存文件夹的自定义属性的隐藏文件,如文件的图标位置或背景色,相当于Windows 的 desktop.ini。
|
1 |
$ defaults write com.apple.desktopservices DSDontWriteNetworkStores -bool TRUE |
|
1 |
$ defaults delete com.apple.desktopservices DSDontWriteNetworkStores |
对于使用验证 Test Case 方法中抛出的异常,我起初想到的是一种比较简单的方法,但是显得比较繁琐:
|
1 2 3 4 5 6 7 8 9 10 11 |
@Test public void testOldStyle() { try { double value = Math.random(); if(value < 0.5) { throw new IllegalStateException("test"); } Assert.fail("Expect IllegalStateException"); } catch(IllegalStateException e) { } } |
Google了一下,找到另外几种更加方便的方法:1,使用Test注解中的expected字段判断抛出异常的类型。2,使用ExpectedException的Rule注解。
个人偏好用Test注解中的expected字段,它先的更加简洁,不管读起来还是写起来都很方便,并且一目了然:
|
1 2 3 4 5 6 7 8 9 |
@Test(expected = IllegalStateException.class) public void testThrowException() { throw new IllegalStateException("test"); } @Test(expected = IllegalStateException.class) public void testNotThrowException() { System.out.println("No Exception throws"); } |
对Rule注解的使用(只有在JUnit4.7以后才有这个功能),它提供了更加强大的功能,它可以同时检查异常类型以及异常消息内容,这些内容可以只包含其中的某些字符,ExpectedException还支持使用hamcrest中的Matcher,默认使用IsInstanceOf和StringContains Matcher。在BlockJUnit4ClassRunner的实现中,每一个Test Case运行时都会重新创建Test Class的实例,因而在使用ExpectedException这个Rule时,不用担心在多个Test Case之间相互影响的问题:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
@Rule public final ExpectedException expectedException = ExpectedException.none(); @Test public void testThrowExceptionWithRule() { expectedException.expect(IllegalStateException.class); throw new IllegalStateException("test"); } @Test public void testThrowExceptionAndMessageWithRule() { expectedException.expect(IllegalStateException.class); expectedException.expectMessage("fail"); throw new IllegalStateException("expect fail"); } |
在stackoverflow中还有人提到了使用google-code中的catch-exception工程,今天没时间看了,回去好好研究一下。
地址是:http://code.google.com/p/catch-exception/