
老开发的心声: 官方何时能真正的去解决BUG,留给UNI的时间不多了。一个bug 反应了,永远是等待,那生态做来干什么
uni其实很适合新手入门,但是,一旦永久了,总是有很多的bug,而有些bug 就是致命性的, u 软件开发了很久,才发现是官方系统性bug, excase me 我怎么修? 反馈问题,提交BUG,运气不好,毛人都找不到一个。运气好,有个官方的人跟你说上几句,然后,说上几句就是让你等,等等,我T吗都工作都要等掉了,还等,一个BUG几个月不修复,我也是醉了, 这样的生态,有什么意思,,
uni 本是国产之光,如今,感觉越来越混, 社区生态不维护好,搞什么 都是暖用。
BUGS:
1 .uni各种闪退(代码正确)
2 录音限制10分钟, 期间,一旦APP进入后台模式隐藏超过60秒,录音就听不到了。。。神bug。。
3.官方蓝牙链接,获取链接上时好时坏, 代码都没问题哈,
- 关键 这些Bug,不是轻易复现的,都是软件开发后了,实际使用才能发现,然后怎么办??找官方?? 官方除了让你等,就是让你等。。。玩鸡毛哦
准备弃坑去RN了。。。
一位使用hubildx 4年的老开发了,真的伤心。
uni其实很适合新手入门,但是,一旦永久了,总是有很多的bug,而有些bug 就是致命性的, u 软件开发了很久,才发现是官方系统性bug, excase me 我怎么修? 反馈问题,提交BUG,运气不好,毛人都找不到一个。运气好,有个官方的人跟你说上几句,然后,说上几句就是让你等,等等,我T吗都工作都要等掉了,还等,一个BUG几个月不修复,我也是醉了, 这样的生态,有什么意思,,
uni 本是国产之光,如今,感觉越来越混, 社区生态不维护好,搞什么 都是暖用。
BUGS:
1 .uni各种闪退(代码正确)
2 录音限制10分钟, 期间,一旦APP进入后台模式隐藏超过60秒,录音就听不到了。。。神bug。。
3.官方蓝牙链接,获取链接上时好时坏, 代码都没问题哈,
- 关键 这些Bug,不是轻易复现的,都是软件开发后了,实际使用才能发现,然后怎么办??找官方?? 官方除了让你等,就是让你等。。。玩鸡毛哦
准备弃坑去RN了。。。
一位使用hubildx 4年的老开发了,真的伤心。

JS 和 Native 互相调用方式
一、网页JS调用Native中java代码
哥斯拉大战金刚下载地址:duan.kim
网页和本地代码的交互主要是通过webview这个桥梁来进行的,webview中的如下接口:
接口中的第一个参数object,为注入webview的java对象
第二个参数name,为暴露给javaScript使用的名字。
即通过该接口给webview注入一个object对象,然后javaScript可以通过name来引用object对象。
Webview的设置如下,打开javaScript功能,加载本地网页,注入对象:
//启用javascript
mWebView.getSettings().setJavaScriptEnabled(true);
//从assets目录下面的加载html
mWebView.loadUrl("file:///android_asset/wx.html");
mWebView.addJavascriptInterface(this,"wx");
native本地定义的java接口:
分别定义了带有参数和不带参数的两个接口,当JS调用的时候,本地会弹出Toast显示文本,并且更新native界面中的textview内容。
网页端调用Native端代码方式如下:
调用方式主要是通过window来引用webview中注入的对象。
需要注意的是在Android4.2之前addJavascriptInterface接口存在注入漏洞,即JS可以通过反射获取到native端的其他接口,进行其他非法操作,所以4.2之后升级增加了JS只能访问带有JavascriptInterface注解的Java函数的限制,在本地定义的提供给JS调用的接口都需要增加android.webkit.JavascriptInterface声明。
二、Native端java调用网页JS方法
网页JS端提供给Java端的代码定义如下,主要用来改变标签内容:
Java端的调用方法如下:
Webview对象通过loadUrl接口来加载以javascript协议头的方式就可以调用JS中定义的接口了。
一、网页JS调用Native中java代码
哥斯拉大战金刚下载地址:duan.kim
网页和本地代码的交互主要是通过webview这个桥梁来进行的,webview中的如下接口:
接口中的第一个参数object,为注入webview的java对象
第二个参数name,为暴露给javaScript使用的名字。
即通过该接口给webview注入一个object对象,然后javaScript可以通过name来引用object对象。
Webview的设置如下,打开javaScript功能,加载本地网页,注入对象:
//启用javascript
mWebView.getSettings().setJavaScriptEnabled(true);
//从assets目录下面的加载html
mWebView.loadUrl("file:///android_asset/wx.html");
mWebView.addJavascriptInterface(this,"wx");
native本地定义的java接口:
分别定义了带有参数和不带参数的两个接口,当JS调用的时候,本地会弹出Toast显示文本,并且更新native界面中的textview内容。
网页端调用Native端代码方式如下:
调用方式主要是通过window来引用webview中注入的对象。
需要注意的是在Android4.2之前addJavascriptInterface接口存在注入漏洞,即JS可以通过反射获取到native端的其他接口,进行其他非法操作,所以4.2之后升级增加了JS只能访问带有JavascriptInterface注解的Java函数的限制,在本地定义的提供给JS调用的接口都需要增加android.webkit.JavascriptInterface声明。
二、Native端java调用网页JS方法
网页JS端提供给Java端的代码定义如下,主要用来改变标签内容:
Java端的调用方法如下:
Webview对象通过loadUrl接口来加载以javascript协议头的方式就可以调用JS中定义的接口了。
收起阅读 »
html5 5+sdk启动白屏
目前两个项目是html加原生一起开发,主要是html,html运用的是hbulider,里面有一个套成型的mui,原生这边主要是做一些插件之类的,html不能满足的功能,不知道是这个sdk适配的不怎么完美还是什么原因,总有一些问题,下面是我遇到的问题:
标题
==启动白屏
这个应该是android原生的问题,原生好处理,加载html,利用这个5+sdk的框架,就会有一些问题,
处理:添加一个启动界面,用原生,设置背景为透明,设置一个主题
<style name="Login" parent="DCloudTheme" >
<!--<item name="android:windowIsTranslucent">true</item>-->
<item name="android:windowBackground">@drawable/splash</item>
<item name="android:windowNoTitle">true</item>
</style>
进来不做任何处理,直接跳转sdkWebApp,我是用这个方式直接
加载的项目。这个sdkwebapp的主题必须设置为dcloud,
加载地图会出现黑屏
这个项目里面有一个考勤界面,需要百度地图
,目前
ios的不会出现跳转时黑屏的问题,android的不行,不知道后期更新会不会解决这个问题
目前两个项目是html加原生一起开发,主要是html,html运用的是hbulider,里面有一个套成型的mui,原生这边主要是做一些插件之类的,html不能满足的功能,不知道是这个sdk适配的不怎么完美还是什么原因,总有一些问题,下面是我遇到的问题:
标题
==启动白屏
这个应该是android原生的问题,原生好处理,加载html,利用这个5+sdk的框架,就会有一些问题,
处理:添加一个启动界面,用原生,设置背景为透明,设置一个主题
<style name="Login" parent="DCloudTheme" >
<!--<item name="android:windowIsTranslucent">true</item>-->
<item name="android:windowBackground">@drawable/splash</item>
<item name="android:windowNoTitle">true</item>
</style>
进来不做任何处理,直接跳转sdkWebApp,我是用这个方式直接
加载的项目。这个sdkwebapp的主题必须设置为dcloud,
加载地图会出现黑屏
这个项目里面有一个考勤界面,需要百度地图
,目前
ios的不会出现跳转时黑屏的问题,android的不行,不知道后期更新会不会解决这个问题

WebSocket介绍和Socket的区别
WebSocket介绍与原理
WebSocket protocol是HTML5一种新的协议。它实现了浏览器与服务器全双工通信(full-duplex)。一开始的握手需要借助HTTP请求完成。
——百度百科
目的:即时通讯,替代轮询
应用场景:网站上的即时通讯是很常见的,比如网页的QQ,聊天系统等。按照以往的技术能力通常是采用轮询、Comet技术解决。
HTTP协议是非持久化的,单向的网络协议,在建立连接后只允许浏览器向服务器发出请求后,服务器才能返回相应的数据。当需要即时通讯时,通过轮询在特定的时间间隔(如1秒),由浏览器向服务器发送Request请求,然后将最新的数据返回给浏览器。这样的方法最明显的缺点就是需要不断的发送请求,而且通常HTTP request的Header是非常长的,为了传输一个很小的数据需要付出巨大的代价,是很不合算的,占用了很多的宽带。
缺点:会导致过多不必要的请求,浪费流量和服务器资源,每一次请求、应答,都浪费了一定流量在相同的头部信息上
然而WebSocket的出现可以弥补这一缺点。在WebSocket中,只需要服务器和浏览器通过HTTP协议进行一个握手的动作,然后单独建立一条TCP的通信通道进行数据的传送。
原理:WebSocket同HTTP一样也是应用层的协议,但是它是一种双向通信协议,是建立在TCP之上的。
连接过程——握手过程
1.浏览器、服务器建立TCP连接,三次握手。这是通信的基础,传输控制层,若失败后续都不执行。
2.TCP连接成功后,浏览器通过HTTP协议向服务器传送WebSocket支持的版本号等信息。(开始前的HTTP握手)
3.服务器收到客户端的握手请求后,同样采用HTTP协议回馈数据。
4.当收到了连接成功的消息后,通过TCP通道进行传输通信。
WebSocket与HTTP的关系
相同点
都是一样基于TCP的,都是可靠性传输协议。
都是应用层协议。
不同点
WebSocket是双向通信协议,模拟Socket协议,可以双向发送或接受信息。HTTP是单向的。
WebSocket是需要握手进行建立连接的。
联系
WebSocket在建立握手时,数据是通过HTTP传输的。但是建立之后,在真正传输时候是不需要HTTP协议的。
WebSocket与Socket的关系
Socket其实并不是一个协议,而是为了方便使用TCP或UDP而抽象出来的一层,是位于应用层和传输控制层之间的一组接口。Socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口。在设计模式中,Socket其实就是一个门面模式,它把复杂的TCP/IP协议族隐藏在Socket接口后面,对用户来说,一组简单的接口就是全部,让Socket去组织数据,以符合指定的协议。当两台主机通信时,必须通过Socket连接,Socket则利用TCP/IP协议建立TCP连接。TCP连接则更依靠于底层的IP协议,IP协议的连接则依赖于链路层等更低层次。WebSocket则是一个典型的应用层协议。Socket是传输控制层协议,WebSocket是应用层协议。
HTML5与WebSocket的关系
WebSocket API是HTML5标准的一部分,但这并不代表WebSocket一定要用在HTML中,或者只能在基于浏览器的应用程序中使用。实际上,许多语言、框架和服务器都提供了WebSocket支持,例如:
*基于C的libwebsocket.org
*基于Node.js的Socket.io
*基于Python的ws4py
*基于C++的WebSocket++
*Apache对WebSocket的支持:Apache Module mod_proxy_wstunnel
*Nginx对WebSockets的支持:NGINX as a WebSockets Proxy、NGINX Announces Support for WebSocket Protocol、WebSocket proxying
*lighttpd对WebSocket的支持:mod_websocket
WebSocket机制
WebSocket是HTML5一种新的协议。它实现了浏览器与服务器全双工通信,能更好的节省服务器资源和带宽并达到实时通讯,它建立在TCP之上,同HTTP一样通过TCP来传输数据,但是它和HTTP最大不同是:
WebSocket是一种双向通信协议,在建立连接后,WebSocket服务器和Browser/Client Agent都能主动的向对方发送或接收数据,就像Socket一样;WebSocket需要类似TCP的客户端和服务器端通过握手连接,连接成功后才能相互通信。
非WebSocket模式传统HTTP客户端与服务器的交互如下图所示:
图1.传统HTTP请求响应客户端服务器交互图
使用WebSocket模式客户端与服务器的交互如下图:
图2.WebSocket请求响应客户端服务器交互图
上图对比可以看出,相对于传统HTTP每次请求-应答都需要客户端与服务端建立连接的模式,WebSocket是类似Socket的TCP长连接的通讯模式,一旦WebSocket连接建立后,后续数据都以帧序列的形式传输。在客户端断开WebSocket连接或Server端断掉连接前,不需要客户端和服务端重新发起连接请求。在海量并发及客户端与服务器交互负载流量大的情况下,极大的节省了网络带宽资源的消耗,有明显的性能优势,且客户端发送和接受消息是在同一个持久连接上发起,实时性优势明显。
我们再通过客户端和服务端交互的报文看一下WebSocket通讯与传统HTTP的不同:
在客户端,new WebSocket实例化一个新的WebSocket客户端对象,连接类似ws://yourdomain:port/path的服务端WebSocket URL,WebSocket客户端对象会自动解析并识别为WebSocket请求,从而连接服务端端口,执行双方握手过程,客户端发送数据格式类似:
清单1.WebSocket客户端连接报文
GET/webfin/websocket/HTTP/1.1
Host:localhost
Upgrade:websocket
Connection:Upgrade
Sec-WebSocket-Key:xqBt3ImNzJbYqRINxEFlkg==
Origin:
http://localhost
:8080
Sec-WebSocket-Version:13
http://localhost
:8080
Sec-WebSocket-Version:13
可以看到,客户端发起的WebSocket连接报文类似传统HTTP报文,”Upgrade:websocket”参数值表明这是WebSocket类型请求,“Sec-WebSocket-Key”是WebSocket客户端发送的一个base64编码的密文,要求服务端必须返回一个对应加密的“Sec-WebSocket-Accept”应答,否则客户端会抛出“Error during WebSocket handshake”错误,并关闭连接。
服务端收到报文后返回的数据格式类似:
清单2.WebSocket服务端响应报文
HTTP/1.1 101 Switching Protocols
Upgrade:websocket
Connection:Upgrade
Sec-WebSocket-Accept:K7DJLdLooIwIG/MOpvWFB3y3FE8=
“Sec-WebSocket-Accept”的值是服务端采用与客户端一致的密钥计算出来后返回客户端的,“HTTP/1.1 101 Switching Protocols”表示服务端接受WebSocket协议的客户端连接,经过这样的请求-响应处理后,客户端服务端的WebSocket连接握手成功,后续就可以进行TCP通讯了。
在开发方面,WebSocket API也十分简单,我们只需要实例化WebSocket,创建连接,然后服务端和客户端就可以相互发送和响应消息,在下文WebSocket实现及案例分析部分,可以看到详细的WebSocket API及代码实现。
WebSocket实现
如上文所述,WebSocket的实现分为客户端和服务端两部分,客户端(通常为浏览器)发出WebSocket连接请求,服务端响应,实现类似TCP握手的动作,从而在浏览器客户端和WebSocket服务端之间形成一条HTTP长连接快速通道。两者之间后续进行直接的数据互相传送,不再需要发起连接和相应。
以下简要描述WebSocket服务端API及客户端API。
WebSocket服务端API
WebSocket服务端在各个主流应用服务器厂商中已基本获得符合JEE JSR356标准规范API的支持,以下列举了部分常见的商用及开源应用服务器对WebSocket Server端的支持情况:
表1.WebSocket服务端支持
厂商应用服务器备注
IBM WebSphere WebSphere 8.0以上版本支持,7.X之前版本结合MQTT支持类似的HTTP长连接
甲骨文WebLogic WebLogic 12c支持,11g及10g版本通过HTTP Publish支持类似的HTTP长连接
微软IIS IIS 7.0+支持
Apache Tomcat Tomcat 7.0.5+支持,7.0.2X及7.0.3X通过自定义API支持
Jetty Jetty 7.0+支持
以下我们使用Tomcat7.0.5版本的服务端示例代码说明WebSocket服务端的实现:
JSR356的WebSocket规范使用javax.websocket.*的API,可以将一个普通Java对象(POJO)使用 ServerEndpoint注释作为WebSocket服务器的端点,代码示例如下:
清单3.WebSocket服务端API示例
ServerEndpoint("/echo")
public class EchoEndpoint{
OnOpen
public void onOpen(Session session)throws IOException{
//以下代码省略...
}
OnMessage
public String onMessage(String message){
//以下代码省略...
}
Message(maxMessageSize=6)
public void receiveMessage(String s){
//以下代码省略...
}
OnError
public void onError(Throwable t){
//以下代码省略...
}
OnClose
public void onClose(Session session,CloseReason reason){
//以下代码省略...
}
}
代码解释:
上文的简洁代码即建立了一个WebSocket的服务端, ServerEndpoint("/echo")的annotation注释端点表示将WebSocket服务端运行在ws://[Server端IP或域名]:[Server端口]/websockets/echo的访问端点,客户端浏览器已经可以对WebSocket客户端API发起HTTP长连接了。
使用ServerEndpoint注释的类必须有一个公共的无参数构造函数, onMessage注解的Java方法用于接收传入的WebSocket信息,这个信息可以是文本格式,也可以是二进制格式。
OnOpen在这个端点一个新的连接建立时被调用。参数提供了连接的另一端的更多细节。Session表明两个WebSocket端点对话连接的另一端,可以理解为类似HTTPSession的概念。
OnClose在连接被终止时调用。参数closeReason可封装更多细节,如为什么一个WebSocket连接关闭。
更高级的定制如 Message注释,MaxMessageSize属性可以被用来定义消息字节最大限制,在示例程序中,如果超过6个字节的信息被接收,就报告错误和连接关闭。
注意:早期不同应用服务器支持的WebSocket方式不尽相同,即使同一厂商,不同版本也有细微差别,如Tomcat服务器7.0.5以上的版本都是标准JSR356规范实现,而7.0.2x/7.0.3X的版本使用自定义API(WebSocketServlet和StreamInbound,前者是一个容器,用来初始化WebSocket环境;后者是用来具体处理WebSocket请求和响应,详见案例分析部分),且Tomcat7.0.3x与7.0.2x的createWebSocketInbound方法的定义不同,增加了一个HttpServletRequest参数,使得可以从request参数中获取更多WebSocket客户端的信息,如下代码所示:
清单4.Tomcat7.0.3X版本WebSocket API
public class EchoServlet extends WebSocketServlet{
Override
protected StreamInbound createWebSocketInbound(String subProtocol,
HttpServletRequest request){
//以下代码省略....
return new MessageInbound(){
//以下代码省略....
}
protected void onBinaryMessage(ByteBuffer buffer)
throws IOException{
//以下代码省略...
}
protected void onTextMessage(CharBuffer buffer)throws IOException{
getWsOutbound().writeTextMessage(buffer);
//以下代码省略...
}
};
}
}
因此选择WebSocket的Server端重点需要选择其版本,通常情况下,更新的版本对WebSocket的支持是标准JSR规范API,但也要考虑开发易用性及老版本程序移植性等方面的问题,如下文所述的客户案例,就是因为客户要求统一应用服务器版本所以使用的Tomcat 7.0.3X版本的WebSocketServlet实现,而不是JSR356的 ServerEndpoint注释端点。
WebSocket客户端API
对于WebSocket客户端,主流的浏览器(包括PC和移动终端)现已都支持标准的HTML5的WebSocket API,这意味着客户端的WebSocket JavaScirpt脚本具备良好的一致性和跨平台特性,以下列举了常见的浏览器厂商对WebSocket的支持情况:
表2.WebSocket客户端支持
浏览器支持情况
Chrome Chrome version 4+支持
Firefox Firefox version 5+支持
IE IE version 10+支持
Safari IOS 5+支持
Android Brower Android 4.5+支持
客户端WebSocket API基本上已经在各个主流浏览器厂商中实现了统一,因此使用标准HTML5定义的WebSocket客户端的JavaScript API即可,当然也可以使用业界满足WebSocket标准规范的开源框架,如Socket.io。
以下以一段代码示例说明WebSocket的客户端实现:
清单5.WebSocket客户端API示例
var ws=new WebSocket(“ws://echo.websocket.org”);
ws.onopen=function(){ws.send(“Test!”);};
ws.onmessage=function(evt){console.log(evt.data);ws.close();};
ws.onclose=function(evt){console.log(“WebSocketClosed!”);};
ws.onerror=function(evt){console.log(“WebSocketError!”);};
第一行代码是在申请一个WebSocket对象,参数是需要连接的服务器端的地址,同HTTP协议开头一样,WebSocket协议的URL使用ws://开头,另外安全的WebSocket协议使用wss://开头。
第二行到第五行为WebSocket对象注册消息的处理函数,WebSocket对象一共支持四个消息onopen,onmessage,onclose和onerror,有了这4个事件,我们就可以很容易很轻松的驾驭WebSocket。
当Browser和WebSocketServer连接成功后,会触发onopen消息;如果连接失败,发送、接收数据失败或者处理数据出现错误,browser会触发onerror消息;当Browser接收到WebSocketServer发送过来的数据时,就会触发onmessage消息,参数evt中包含Server传输过来的数据;当Browser接收到WebSocketServer端发送的关闭连接请求时,就会触发onclose消息。我们可以看出所有的操作都是采用异步回调的方式触发,这样不会阻塞UI,可以获得更快的响应时间,更好的用户体验。
WebSocket介绍与原理
WebSocket protocol是HTML5一种新的协议。它实现了浏览器与服务器全双工通信(full-duplex)。一开始的握手需要借助HTTP请求完成。
——百度百科
目的:即时通讯,替代轮询
应用场景:网站上的即时通讯是很常见的,比如网页的QQ,聊天系统等。按照以往的技术能力通常是采用轮询、Comet技术解决。
HTTP协议是非持久化的,单向的网络协议,在建立连接后只允许浏览器向服务器发出请求后,服务器才能返回相应的数据。当需要即时通讯时,通过轮询在特定的时间间隔(如1秒),由浏览器向服务器发送Request请求,然后将最新的数据返回给浏览器。这样的方法最明显的缺点就是需要不断的发送请求,而且通常HTTP request的Header是非常长的,为了传输一个很小的数据需要付出巨大的代价,是很不合算的,占用了很多的宽带。
缺点:会导致过多不必要的请求,浪费流量和服务器资源,每一次请求、应答,都浪费了一定流量在相同的头部信息上
然而WebSocket的出现可以弥补这一缺点。在WebSocket中,只需要服务器和浏览器通过HTTP协议进行一个握手的动作,然后单独建立一条TCP的通信通道进行数据的传送。
原理:WebSocket同HTTP一样也是应用层的协议,但是它是一种双向通信协议,是建立在TCP之上的。
连接过程——握手过程
1.浏览器、服务器建立TCP连接,三次握手。这是通信的基础,传输控制层,若失败后续都不执行。
2.TCP连接成功后,浏览器通过HTTP协议向服务器传送WebSocket支持的版本号等信息。(开始前的HTTP握手)
3.服务器收到客户端的握手请求后,同样采用HTTP协议回馈数据。
4.当收到了连接成功的消息后,通过TCP通道进行传输通信。
WebSocket与HTTP的关系
相同点
都是一样基于TCP的,都是可靠性传输协议。
都是应用层协议。
不同点
WebSocket是双向通信协议,模拟Socket协议,可以双向发送或接受信息。HTTP是单向的。
WebSocket是需要握手进行建立连接的。
联系
WebSocket在建立握手时,数据是通过HTTP传输的。但是建立之后,在真正传输时候是不需要HTTP协议的。
WebSocket与Socket的关系
Socket其实并不是一个协议,而是为了方便使用TCP或UDP而抽象出来的一层,是位于应用层和传输控制层之间的一组接口。Socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口。在设计模式中,Socket其实就是一个门面模式,它把复杂的TCP/IP协议族隐藏在Socket接口后面,对用户来说,一组简单的接口就是全部,让Socket去组织数据,以符合指定的协议。当两台主机通信时,必须通过Socket连接,Socket则利用TCP/IP协议建立TCP连接。TCP连接则更依靠于底层的IP协议,IP协议的连接则依赖于链路层等更低层次。WebSocket则是一个典型的应用层协议。Socket是传输控制层协议,WebSocket是应用层协议。
HTML5与WebSocket的关系
WebSocket API是HTML5标准的一部分,但这并不代表WebSocket一定要用在HTML中,或者只能在基于浏览器的应用程序中使用。实际上,许多语言、框架和服务器都提供了WebSocket支持,例如:
*基于C的libwebsocket.org
*基于Node.js的Socket.io
*基于Python的ws4py
*基于C++的WebSocket++
*Apache对WebSocket的支持:Apache Module mod_proxy_wstunnel
*Nginx对WebSockets的支持:NGINX as a WebSockets Proxy、NGINX Announces Support for WebSocket Protocol、WebSocket proxying
*lighttpd对WebSocket的支持:mod_websocket
WebSocket机制
WebSocket是HTML5一种新的协议。它实现了浏览器与服务器全双工通信,能更好的节省服务器资源和带宽并达到实时通讯,它建立在TCP之上,同HTTP一样通过TCP来传输数据,但是它和HTTP最大不同是:
WebSocket是一种双向通信协议,在建立连接后,WebSocket服务器和Browser/Client Agent都能主动的向对方发送或接收数据,就像Socket一样;WebSocket需要类似TCP的客户端和服务器端通过握手连接,连接成功后才能相互通信。
非WebSocket模式传统HTTP客户端与服务器的交互如下图所示:
图1.传统HTTP请求响应客户端服务器交互图
使用WebSocket模式客户端与服务器的交互如下图:
图2.WebSocket请求响应客户端服务器交互图
上图对比可以看出,相对于传统HTTP每次请求-应答都需要客户端与服务端建立连接的模式,WebSocket是类似Socket的TCP长连接的通讯模式,一旦WebSocket连接建立后,后续数据都以帧序列的形式传输。在客户端断开WebSocket连接或Server端断掉连接前,不需要客户端和服务端重新发起连接请求。在海量并发及客户端与服务器交互负载流量大的情况下,极大的节省了网络带宽资源的消耗,有明显的性能优势,且客户端发送和接受消息是在同一个持久连接上发起,实时性优势明显。
我们再通过客户端和服务端交互的报文看一下WebSocket通讯与传统HTTP的不同:
在客户端,new WebSocket实例化一个新的WebSocket客户端对象,连接类似ws://yourdomain:port/path的服务端WebSocket URL,WebSocket客户端对象会自动解析并识别为WebSocket请求,从而连接服务端端口,执行双方握手过程,客户端发送数据格式类似:
清单1.WebSocket客户端连接报文
GET/webfin/websocket/HTTP/1.1
Host:localhost
Upgrade:websocket
Connection:Upgrade
Sec-WebSocket-Key:xqBt3ImNzJbYqRINxEFlkg==
Origin:
http://localhost
:8080
Sec-WebSocket-Version:13
http://localhost
:8080
Sec-WebSocket-Version:13
可以看到,客户端发起的WebSocket连接报文类似传统HTTP报文,”Upgrade:websocket”参数值表明这是WebSocket类型请求,“Sec-WebSocket-Key”是WebSocket客户端发送的一个base64编码的密文,要求服务端必须返回一个对应加密的“Sec-WebSocket-Accept”应答,否则客户端会抛出“Error during WebSocket handshake”错误,并关闭连接。
服务端收到报文后返回的数据格式类似:
清单2.WebSocket服务端响应报文
HTTP/1.1 101 Switching Protocols
Upgrade:websocket
Connection:Upgrade
Sec-WebSocket-Accept:K7DJLdLooIwIG/MOpvWFB3y3FE8=
“Sec-WebSocket-Accept”的值是服务端采用与客户端一致的密钥计算出来后返回客户端的,“HTTP/1.1 101 Switching Protocols”表示服务端接受WebSocket协议的客户端连接,经过这样的请求-响应处理后,客户端服务端的WebSocket连接握手成功,后续就可以进行TCP通讯了。
在开发方面,WebSocket API也十分简单,我们只需要实例化WebSocket,创建连接,然后服务端和客户端就可以相互发送和响应消息,在下文WebSocket实现及案例分析部分,可以看到详细的WebSocket API及代码实现。
WebSocket实现
如上文所述,WebSocket的实现分为客户端和服务端两部分,客户端(通常为浏览器)发出WebSocket连接请求,服务端响应,实现类似TCP握手的动作,从而在浏览器客户端和WebSocket服务端之间形成一条HTTP长连接快速通道。两者之间后续进行直接的数据互相传送,不再需要发起连接和相应。
以下简要描述WebSocket服务端API及客户端API。
WebSocket服务端API
WebSocket服务端在各个主流应用服务器厂商中已基本获得符合JEE JSR356标准规范API的支持,以下列举了部分常见的商用及开源应用服务器对WebSocket Server端的支持情况:
表1.WebSocket服务端支持
厂商应用服务器备注
IBM WebSphere WebSphere 8.0以上版本支持,7.X之前版本结合MQTT支持类似的HTTP长连接
甲骨文WebLogic WebLogic 12c支持,11g及10g版本通过HTTP Publish支持类似的HTTP长连接
微软IIS IIS 7.0+支持
Apache Tomcat Tomcat 7.0.5+支持,7.0.2X及7.0.3X通过自定义API支持
Jetty Jetty 7.0+支持
以下我们使用Tomcat7.0.5版本的服务端示例代码说明WebSocket服务端的实现:
JSR356的WebSocket规范使用javax.websocket.*的API,可以将一个普通Java对象(POJO)使用 ServerEndpoint注释作为WebSocket服务器的端点,代码示例如下:
清单3.WebSocket服务端API示例
ServerEndpoint("/echo")
public class EchoEndpoint{
OnOpen
public void onOpen(Session session)throws IOException{
//以下代码省略...
}
OnMessage
public String onMessage(String message){
//以下代码省略...
}
Message(maxMessageSize=6)
public void receiveMessage(String s){
//以下代码省略...
}
OnError
public void onError(Throwable t){
//以下代码省略...
}
OnClose
public void onClose(Session session,CloseReason reason){
//以下代码省略...
}
}
代码解释:
上文的简洁代码即建立了一个WebSocket的服务端, ServerEndpoint("/echo")的annotation注释端点表示将WebSocket服务端运行在ws://[Server端IP或域名]:[Server端口]/websockets/echo的访问端点,客户端浏览器已经可以对WebSocket客户端API发起HTTP长连接了。
使用ServerEndpoint注释的类必须有一个公共的无参数构造函数, onMessage注解的Java方法用于接收传入的WebSocket信息,这个信息可以是文本格式,也可以是二进制格式。
OnOpen在这个端点一个新的连接建立时被调用。参数提供了连接的另一端的更多细节。Session表明两个WebSocket端点对话连接的另一端,可以理解为类似HTTPSession的概念。
OnClose在连接被终止时调用。参数closeReason可封装更多细节,如为什么一个WebSocket连接关闭。
更高级的定制如 Message注释,MaxMessageSize属性可以被用来定义消息字节最大限制,在示例程序中,如果超过6个字节的信息被接收,就报告错误和连接关闭。
注意:早期不同应用服务器支持的WebSocket方式不尽相同,即使同一厂商,不同版本也有细微差别,如Tomcat服务器7.0.5以上的版本都是标准JSR356规范实现,而7.0.2x/7.0.3X的版本使用自定义API(WebSocketServlet和StreamInbound,前者是一个容器,用来初始化WebSocket环境;后者是用来具体处理WebSocket请求和响应,详见案例分析部分),且Tomcat7.0.3x与7.0.2x的createWebSocketInbound方法的定义不同,增加了一个HttpServletRequest参数,使得可以从request参数中获取更多WebSocket客户端的信息,如下代码所示:
清单4.Tomcat7.0.3X版本WebSocket API
public class EchoServlet extends WebSocketServlet{
Override
protected StreamInbound createWebSocketInbound(String subProtocol,
HttpServletRequest request){
//以下代码省略....
return new MessageInbound(){
//以下代码省略....
}
protected void onBinaryMessage(ByteBuffer buffer)
throws IOException{
//以下代码省略...
}
protected void onTextMessage(CharBuffer buffer)throws IOException{
getWsOutbound().writeTextMessage(buffer);
//以下代码省略...
}
};
}
}
因此选择WebSocket的Server端重点需要选择其版本,通常情况下,更新的版本对WebSocket的支持是标准JSR规范API,但也要考虑开发易用性及老版本程序移植性等方面的问题,如下文所述的客户案例,就是因为客户要求统一应用服务器版本所以使用的Tomcat 7.0.3X版本的WebSocketServlet实现,而不是JSR356的 ServerEndpoint注释端点。
WebSocket客户端API
对于WebSocket客户端,主流的浏览器(包括PC和移动终端)现已都支持标准的HTML5的WebSocket API,这意味着客户端的WebSocket JavaScirpt脚本具备良好的一致性和跨平台特性,以下列举了常见的浏览器厂商对WebSocket的支持情况:
表2.WebSocket客户端支持
浏览器支持情况
Chrome Chrome version 4+支持
Firefox Firefox version 5+支持
IE IE version 10+支持
Safari IOS 5+支持
Android Brower Android 4.5+支持
客户端WebSocket API基本上已经在各个主流浏览器厂商中实现了统一,因此使用标准HTML5定义的WebSocket客户端的JavaScript API即可,当然也可以使用业界满足WebSocket标准规范的开源框架,如Socket.io。
以下以一段代码示例说明WebSocket的客户端实现:
清单5.WebSocket客户端API示例
var ws=new WebSocket(“ws://echo.websocket.org”);
ws.onopen=function(){ws.send(“Test!”);};
ws.onmessage=function(evt){console.log(evt.data);ws.close();};
ws.onclose=function(evt){console.log(“WebSocketClosed!”);};
ws.onerror=function(evt){console.log(“WebSocketError!”);};
第一行代码是在申请一个WebSocket对象,参数是需要连接的服务器端的地址,同HTTP协议开头一样,WebSocket协议的URL使用ws://开头,另外安全的WebSocket协议使用wss://开头。
第二行到第五行为WebSocket对象注册消息的处理函数,WebSocket对象一共支持四个消息onopen,onmessage,onclose和onerror,有了这4个事件,我们就可以很容易很轻松的驾驭WebSocket。
当Browser和WebSocketServer连接成功后,会触发onopen消息;如果连接失败,发送、接收数据失败或者处理数据出现错误,browser会触发onerror消息;当Browser接收到WebSocketServer发送过来的数据时,就会触发onmessage消息,参数evt中包含Server传输过来的数据;当Browser接收到WebSocketServer端发送的关闭连接请求时,就会触发onclose消息。我们可以看出所有的操作都是采用异步回调的方式触发,这样不会阻塞UI,可以获得更快的响应时间,更好的用户体验。
收起阅读 »
使用网站域名封装Web2App
wap2app是什么
哥斯拉大战金刚下载地址:duan.kim
wap2app是一个将现有M站(也称手机wap站,区别于pc的web站)快速发布成App的增强方案,通过DCloud的wap2app框架,进行简单的配置和必要的编程,即可完成M站的体验强化,达到原生应用的功能体验,进而再发布为原生安装包或流应用。
下载/登录开发工具
前往dcloud.io根据自己的操作系统,下载对应的HBuilder安装包,解压即可使用。
PS:首次使用需注册一个开发者账号,方便后续的打包以及应用管理。
创建项目
按照如下步骤在HBuilder中新建wap2app工程
顶部菜单,文件->新建->Wap2App
输入应用名称、wap站首页地址,点击“完成”
工程建成后,默认目录结构如下:
配置应用图标及启动图
应用图标
应用图标是App安装到手机后,在手机桌面显示的图标;按照如下步骤配置应用图标:
双击打开manifest.json文件,点击下方“图标配置”选项卡
在图标配置页面,按照要求配置各种分辨率的图标
建议配置1024*1024的大图标,然后自动生成并替换各种分辨率的图标。
启动图片
启动图片是用户从点击桌面图标到进入应用首页中间显示的欢迎图片;按照如下步骤配置应用图标。
点击“启动图片(splash)配置”选项卡,会打开启动图配置界面
根据需要配置不同分辨率的启动图片,例如仅生成Android安装包,则仅配置Android启动图片即可。
应用发布
wap2app项目可以打包成iOS平台的ipa安装包、Android平台的apk安装包。
在HBuilder中,点击顶部“发行”菜单,点击“云打包-打原生安装包”,如下:
打开原生打包配置界面,如下图所示:
选择需要打包的平台(iOS平台打包需要配置iOS证书),点击“打包”按钮即可提交云端打包,打包完成后会自动下载安装包,安装到手机即可体验。
wap2app是什么
哥斯拉大战金刚下载地址:duan.kim
wap2app是一个将现有M站(也称手机wap站,区别于pc的web站)快速发布成App的增强方案,通过DCloud的wap2app框架,进行简单的配置和必要的编程,即可完成M站的体验强化,达到原生应用的功能体验,进而再发布为原生安装包或流应用。
下载/登录开发工具
前往dcloud.io根据自己的操作系统,下载对应的HBuilder安装包,解压即可使用。
PS:首次使用需注册一个开发者账号,方便后续的打包以及应用管理。
创建项目
按照如下步骤在HBuilder中新建wap2app工程
顶部菜单,文件->新建->Wap2App
输入应用名称、wap站首页地址,点击“完成”
工程建成后,默认目录结构如下:
配置应用图标及启动图
应用图标
应用图标是App安装到手机后,在手机桌面显示的图标;按照如下步骤配置应用图标:
双击打开manifest.json文件,点击下方“图标配置”选项卡
在图标配置页面,按照要求配置各种分辨率的图标
建议配置1024*1024的大图标,然后自动生成并替换各种分辨率的图标。
启动图片
启动图片是用户从点击桌面图标到进入应用首页中间显示的欢迎图片;按照如下步骤配置应用图标。
点击“启动图片(splash)配置”选项卡,会打开启动图配置界面
根据需要配置不同分辨率的启动图片,例如仅生成Android安装包,则仅配置Android启动图片即可。
应用发布
wap2app项目可以打包成iOS平台的ipa安装包、Android平台的apk安装包。
在HBuilder中,点击顶部“发行”菜单,点击“云打包-打原生安装包”,如下:
打开原生打包配置界面,如下图所示:
选择需要打包的平台(iOS平台打包需要配置iOS证书),点击“打包”按钮即可提交云端打包,打包完成后会自动下载安装包,安装到手机即可体验。
收起阅读 »
C++的35个技巧阅读笔记(一)
1.仔细区别指针和引用
1、引用必须代表某个对象,没有所谓null引用,因此必须有初值。
2、使用引用可能会比使用指针更有效率,因为使用引用之前不需要测试其有效性。
3、指针可以被重新赋值,指向另一个对象,指针 却总是指向(代表)它最初获得的那个对象。
string s1("Nancy");
string s2("Clancy");
string& rs = s1; //rs代表s1
string *ps = &s1; //ps指向s1
rs = s2; //rs任然代表s1,但是s1的值现在变成了“Clancy”
ps = &s2; //ps现在指向s2,s1没有变化。
1
2
3
4
5
6
使用引用:
1、确定“总是会代表某个对象”,而且“一旦代表了该对象就不能够再改变”。
2、当实现某些操作符时候,例如:operator[] ,必须返回某种“能够被当作assignment赋值对象”的东西:引用。
3、当实现一个操作符而其语法需求无法由pointers 达成,就选择reference,其他任何时候,请采用pointers。
使用指针:
需要考虑“不指向任何对象”的可能性,或考虑“在不同时间指向不同对象”的能力。
不同点:
1、指针是一个变量,引用是别名。
2、对引用求地址,就是对目标变量求地址。即引用名是目标变量名的一个别名。引用在定义上是说引用不占据任何内存空间,但是编译器在一般将其实现为const指针,即指向位置不可变的指针,所以引用实际上与一般指针同样占用内存。。3、指针有多级,但是引用只能是一级(int **p;合法 而 int &&a是不合法的)。
4、“sizeof引用”得到的是所指向的变量(对象)的大小,而”sizeof指针”得到的是指针本身的大小。
5、指针和引用的自增(++)运算意义不一样;
6、引用常见的使用用途:作为函数的参数、函数的返回值。
1.仔细区别指针和引用
1、引用必须代表某个对象,没有所谓null引用,因此必须有初值。
2、使用引用可能会比使用指针更有效率,因为使用引用之前不需要测试其有效性。
3、指针可以被重新赋值,指向另一个对象,指针 却总是指向(代表)它最初获得的那个对象。
string s1("Nancy");
string s2("Clancy");
string& rs = s1; //rs代表s1
string *ps = &s1; //ps指向s1
rs = s2; //rs任然代表s1,但是s1的值现在变成了“Clancy”
ps = &s2; //ps现在指向s2,s1没有变化。
1
2
3
4
5
6
使用引用:
1、确定“总是会代表某个对象”,而且“一旦代表了该对象就不能够再改变”。
2、当实现某些操作符时候,例如:operator[] ,必须返回某种“能够被当作assignment赋值对象”的东西:引用。
3、当实现一个操作符而其语法需求无法由pointers 达成,就选择reference,其他任何时候,请采用pointers。
使用指针:
需要考虑“不指向任何对象”的可能性,或考虑“在不同时间指向不同对象”的能力。
不同点:
1、指针是一个变量,引用是别名。
2、对引用求地址,就是对目标变量求地址。即引用名是目标变量名的一个别名。引用在定义上是说引用不占据任何内存空间,但是编译器在一般将其实现为const指针,即指向位置不可变的指针,所以引用实际上与一般指针同样占用内存。。3、指针有多级,但是引用只能是一级(int **p;合法 而 int &&a是不合法的)。
4、“sizeof引用”得到的是所指向的变量(对象)的大小,而”sizeof指针”得到的是指针本身的大小。
5、指针和引用的自增(++)运算意义不一样;
6、引用常见的使用用途:作为函数的参数、函数的返回值。

用uniapp开发的app一次性上架appstore和google play,开心一下
以为需要多修改几次呢,出乎意料的顺利,一次提交就上架了,开心一下。
同时也让更多人放心使用uniapp,上架不是问题呢,不会因为非原生就拒绝的
类型:后端基于discuz的社区帖子
uniapp: 纯nvue
appstore 地址 https://apps.apple.com/cn/app/id1560534288
以为需要多修改几次呢,出乎意料的顺利,一次提交就上架了,开心一下。
同时也让更多人放心使用uniapp,上架不是问题呢,不会因为非原生就拒绝的
类型:后端基于discuz的社区帖子
uniapp: 纯nvue
appstore 地址 https://apps.apple.com/cn/app/id1560534288
收起阅读 »
Vite2.x+Electron12整合开发vue3.0直播+聊天+小视频应用
项目介绍
之前有给大家分享一个electron+vue3开发聊天程序,这次分享最新研发的vite2+electron仿抖音短视频应用。
Vite2-ElectronDouYin:基于vite.js搭建electron+vue3仿抖音短视频/直播程序。使用了vite2+vue3+electron12+vant3.x+swiper等技术开发实现。支持上下左右拖拽滑动、键盘上下键滑动切换小视频。
实现了类似抖音聊天功能,支持图片预览、链接/视频新窗口查看、截图/红包等功能。
技术栈
- 编码+技术:vscode / vite2.x+vue3.0+vuex4+vue-router@4
- 跨端框架:electron12.0.1
- UI组件库:vant3 (有赞vue3移动端组件库)
- 弹窗组件:v3popup(vue3自定义弹窗组件)
- 打包工具:vue-cli-plugin-electron-builder
项目结构目录
vite.config.js配置
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import path from 'path'
// https://vitejs.dev/config/
export default defineConfig({
plugins: [vue()],
// base: '/',
// mode: 'development' //production
build: {
/**
* 输出文件目录
* @default dist(默认)
*/
// outDir: 'target',
},
// 环境配置
server: {
// 端口
port: 3000,
// 是否浏览器自动打开
open: false,
// 开启https
https: false,
// 代理配置
proxy: {
// ...
}
},
resolve: {
// 设置路径别名
alias: {
'@': path.resolve(__dirname, '../src'),
}
}
})
vite2.x+electron自定义顶部菜单栏
为了使得项目整体UI的一致性,采用了无边框模式。顶部导航栏采用自定义拖拽实现。
组件进行封装后,通过如下方式调用即可。
<WinBar bgcolor="transparent" transparent>
<template #wbtn>
<a class="wbtn" @click="isShowPersonalCard=true"><i class="iconfont icon-erweima"></i></a>
<a class="wbtn" @click="isShowSideMenu=true"><i class="iconfont icon-menu"></i></a>
</template>
</WinBar>
<WinBar bgcolor="linear-gradient(to right, #36384a, #36384a)">
<template #title>视频预览</template>
<template #wbtn>
<a class="wbtn" @click="handleDownLoad"><i class="iconfont icon-down"></i></a>
</template>
</WinBar>
至于具体如何实现,由于之前有过相关的分享文章,感兴趣的可以去看下。
Electron12自定义系统托盘|托盘图标闪烁
electron文档中有提供Menu和Tray,所以创建系统托盘非常简单。
createTray() {
const trayMenu = Menu.buildFromTemplate([
{
label: '我在线上', icon: path.join(__dirname, '../resource/icon-online.png'),
click: () => null
},
{
label: '隐身', icon: path.join(__dirname, '../resource/icon-invisible.png'),
click: () => null
},
{type: 'separator'},
{
label: '关闭消息闪动', click: () => {
this.flashTray(false)
}
},
{type: 'separator'},
{
label: '显示窗口', click: () => {
try {
for(let i in this.winLs) {
let win = this.getWin(i)
if(!win) return
if(win.isMinimized()) win.restore()
win.show()
}
} catch (error) {
console.log(error)
}
}
},
{
label: '退出', click: () => {
try {
for(let i in this.winLs) {
let win = this.getWin(i)
if(win) win.webContents.send('win-logout')
}
app.quit()
} catch (error) {
console.log(error)
}
}
},
])
this.tray = new Tray(this.trayIco1)
this.tray.setContextMenu(trayMenu)
this.tray.setToolTip(app.name)
}
事先准备好两张大小一样的ico图标,其中一个透明即可。通过定时器来控制闪烁效果。
// 托盘图标闪烁
flashTray(flash) {
let hasIco = false
if(flash) {
if(this.flashTimer) return
this.flashTimer = setInterval(() => {
this.tray.setImage(hasIco ? this.trayIco1 : this.trayIco2)
hasIco = !hasIco
}, 500)
}else {
if(this.flashTimer) {
clearInterval(this.flashTimer)
this.flashTimer = null
}
this.tray.setImage(this.trayIco1)
}
}
// 销毁托盘图标
destoryTray() {
this.flashTray(false)
this.tray.destroy()
this.tray = null
}
vite2.x+electron打包配置参数
在项目根目录下新建一个electron-builder.json打包配置文件。
/**
* @Desc electron打包配置
* @Create andy by 2021-03 Q:282310962 wx:xy190310
*/
{
"productName": "electron-douyin", //项目名称 打包生成exe的前缀名
"appId": "com.example.electrondouyin", //包名
"compression": "maximum", //store|normal|maximum 打包压缩情况(store速度较快)
"artifactName": "${productName}-${version}-${platform}-${arch}.${ext}", //打包后安装包名称
// "directories": {
// "output": "build", //输出文件夹(默认dist_electron)
// },
"asar": false, //asar打包
// 拷贝静态资源目录到指定位置(如根目录下的static文件夹会拷贝至打包后的dist_electron/win-unpacked/resources/static目录)
"extraResources": [
{
"from": "/static",
"to": "static"
},
],
"nsis": {
"oneClick": false, //一键安装
"allowToChangeInstallationDirectory": true, //允许修改安装目录
"perMachine": true, //是否开启安装时权限设置(此电脑或当前用户)
"artifactName": "${productName}-${version}-${platform}-${arch}-setup.${ext}", //打包后安装包名称
"deleteAppDataOnUninstall": true, //卸载时删除数据
"createDesktopShortcut": true, //创建桌面图标
"createStartMenuShortcut": true, //创建开始菜单图标
"shortcutName": "ElectronDouYin", //桌面快捷键图标名称
},
"win": {
"icon": "/static/shortcut.ico", //图标路径
}
}
Okey,整合vite.js+electron跨端开发仿制抖音EXE短视频就分享到这里。
链接:https://www.imooc.com/article/316009
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
项目介绍
之前有给大家分享一个electron+vue3开发聊天程序,这次分享最新研发的vite2+electron仿抖音短视频应用。
Vite2-ElectronDouYin:基于vite.js搭建electron+vue3仿抖音短视频/直播程序。使用了vite2+vue3+electron12+vant3.x+swiper等技术开发实现。支持上下左右拖拽滑动、键盘上下键滑动切换小视频。
实现了类似抖音聊天功能,支持图片预览、链接/视频新窗口查看、截图/红包等功能。
技术栈
- 编码+技术:vscode / vite2.x+vue3.0+vuex4+vue-router@4
- 跨端框架:electron12.0.1
- UI组件库:vant3 (有赞vue3移动端组件库)
- 弹窗组件:v3popup(vue3自定义弹窗组件)
- 打包工具:vue-cli-plugin-electron-builder
项目结构目录
vite.config.js配置
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import path from 'path'
// https://vitejs.dev/config/
export default defineConfig({
plugins: [vue()],
// base: '/',
// mode: 'development' //production
build: {
/**
* 输出文件目录
* @default dist(默认)
*/
// outDir: 'target',
},
// 环境配置
server: {
// 端口
port: 3000,
// 是否浏览器自动打开
open: false,
// 开启https
https: false,
// 代理配置
proxy: {
// ...
}
},
resolve: {
// 设置路径别名
alias: {
'@': path.resolve(__dirname, '../src'),
}
}
})
vite2.x+electron自定义顶部菜单栏
为了使得项目整体UI的一致性,采用了无边框模式。顶部导航栏采用自定义拖拽实现。
组件进行封装后,通过如下方式调用即可。
<WinBar bgcolor="transparent" transparent>
<template #wbtn>
<a class="wbtn" @click="isShowPersonalCard=true"><i class="iconfont icon-erweima"></i></a>
<a class="wbtn" @click="isShowSideMenu=true"><i class="iconfont icon-menu"></i></a>
</template>
</WinBar>
<WinBar bgcolor="linear-gradient(to right, #36384a, #36384a)">
<template #title>视频预览</template>
<template #wbtn>
<a class="wbtn" @click="handleDownLoad"><i class="iconfont icon-down"></i></a>
</template>
</WinBar>
至于具体如何实现,由于之前有过相关的分享文章,感兴趣的可以去看下。
Electron12自定义系统托盘|托盘图标闪烁
electron文档中有提供Menu和Tray,所以创建系统托盘非常简单。
createTray() {
const trayMenu = Menu.buildFromTemplate([
{
label: '我在线上', icon: path.join(__dirname, '../resource/icon-online.png'),
click: () => null
},
{
label: '隐身', icon: path.join(__dirname, '../resource/icon-invisible.png'),
click: () => null
},
{type: 'separator'},
{
label: '关闭消息闪动', click: () => {
this.flashTray(false)
}
},
{type: 'separator'},
{
label: '显示窗口', click: () => {
try {
for(let i in this.winLs) {
let win = this.getWin(i)
if(!win) return
if(win.isMinimized()) win.restore()
win.show()
}
} catch (error) {
console.log(error)
}
}
},
{
label: '退出', click: () => {
try {
for(let i in this.winLs) {
let win = this.getWin(i)
if(win) win.webContents.send('win-logout')
}
app.quit()
} catch (error) {
console.log(error)
}
}
},
])
this.tray = new Tray(this.trayIco1)
this.tray.setContextMenu(trayMenu)
this.tray.setToolTip(app.name)
}
事先准备好两张大小一样的ico图标,其中一个透明即可。通过定时器来控制闪烁效果。
// 托盘图标闪烁
flashTray(flash) {
let hasIco = false
if(flash) {
if(this.flashTimer) return
this.flashTimer = setInterval(() => {
this.tray.setImage(hasIco ? this.trayIco1 : this.trayIco2)
hasIco = !hasIco
}, 500)
}else {
if(this.flashTimer) {
clearInterval(this.flashTimer)
this.flashTimer = null
}
this.tray.setImage(this.trayIco1)
}
}
// 销毁托盘图标
destoryTray() {
this.flashTray(false)
this.tray.destroy()
this.tray = null
}
vite2.x+electron打包配置参数
在项目根目录下新建一个electron-builder.json打包配置文件。
/**
* @Desc electron打包配置
* @Create andy by 2021-03 Q:282310962 wx:xy190310
*/
{
"productName": "electron-douyin", //项目名称 打包生成exe的前缀名
"appId": "com.example.electrondouyin", //包名
"compression": "maximum", //store|normal|maximum 打包压缩情况(store速度较快)
"artifactName": "${productName}-${version}-${platform}-${arch}.${ext}", //打包后安装包名称
// "directories": {
// "output": "build", //输出文件夹(默认dist_electron)
// },
"asar": false, //asar打包
// 拷贝静态资源目录到指定位置(如根目录下的static文件夹会拷贝至打包后的dist_electron/win-unpacked/resources/static目录)
"extraResources": [
{
"from": "/static",
"to": "static"
},
],
"nsis": {
"oneClick": false, //一键安装
"allowToChangeInstallationDirectory": true, //允许修改安装目录
"perMachine": true, //是否开启安装时权限设置(此电脑或当前用户)
"artifactName": "${productName}-${version}-${platform}-${arch}-setup.${ext}", //打包后安装包名称
"deleteAppDataOnUninstall": true, //卸载时删除数据
"createDesktopShortcut": true, //创建桌面图标
"createStartMenuShortcut": true, //创建开始菜单图标
"shortcutName": "ElectronDouYin", //桌面快捷键图标名称
},
"win": {
"icon": "/static/shortcut.ico", //图标路径
}
}
Okey,整合vite.js+electron跨端开发仿制抖音EXE短视频就分享到这里。
链接:https://www.imooc.com/article/316009
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

打包时提示:该账号绑定的手机号被多个账号同时使用 这个问题怎么处理
打包时提示:该账号绑定的手机号被多个账号同时使用 这个问题怎么处理
打包时提示:该账号绑定的手机号被多个账号同时使用 这个问题怎么处理