Duilib嵌入CEF以及JavaScript与C++交互
转载:http://blog.csdn.net/foruok/article/details/50573612
转载:http://blog.csdn.net/foruok/article/details/50584985
转载:http://blog.csdn.net/mfcing/article/details/44539035
转载:https://github.com/fanfeilong/cefutil/blob/master/doc/CEF_JavaScript_Cpp.md
转载:https://blog.csdn.net/aseseven/article/details/79482515(CEF3加载本地HTML文件时中文路径乱码的问题解决办法)
转载:https://blog.csdn.net/u012778714/article/category/7003599
JS与Native代码交互,是在Render进程中,所以我们要实现CefRenderProcessHandler接口
一、JS 调用 C++
- JavaScript注册函数给Render进程,Render进程保存该JavaScript函数
- Render进程发消息通知Browser进程
- Browser进程处理后,回发消息给Render进程
- Render进程调用之前保存的JavaScript函数
1.带参数没有返回值
自己的APP类要继承于CefRenderProcessHandler
#ifndef _CEFBROWSERAPP_H_
#define _CEFBROWSERAPP_H_
#include "include/cef_app.h"
#include "CEFV8HandlerEx.h" class CCefBrowserApp
: public CefApp
, public CefBrowserProcessHandler
, public CefRenderProcessHandler
{
public:
CCefBrowserApp(); virtual ~CCefBrowserApp(); public:
virtual CefRefPtr<CefBrowserProcessHandler> GetBrowserProcessHandler()OVERRIDE { return this; }; public:
// CefBrowserProcessHandler methods:
virtual void OnContextInitialized(); //CefRenderProcessHandler methods
virtual void OnWebKitInitialized(); CefRefPtr<CefRenderProcessHandler> GetRenderProcessHandler() OVERRIDE{ return this; } virtual void OnContextCreated(CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame, CefRefPtr<CefV8Context> context); virtual void OnContextReleased(CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame, CefRefPtr<CefV8Context> context); protected: CefRefPtr<CCEFV8HandlerEx> m_v8Handler; IMPLEMENT_REFCOUNTING(CCefBrowserApp);
};
#endif //_CEFBROWSERAPP_H_
.cpp
#include "CefBrowserApp.h"
#include "stdafx.h" CCefBrowserApp::CCefBrowserApp()
:m_v8Handler(new CCEFV8HandlerEx)
{
} CCefBrowserApp::~CCefBrowserApp()
{
} void CCefBrowserApp::OnContextInitialized()
{
// do nothing here, because we will create browser in my own dialog
} void CCefBrowserApp::OnContextCreated(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
CefRefPtr<CefV8Context> context)
{
// Retrieve the context's window object.
CefRefPtr<CefV8Value> object = context->GetGlobal(); // Create the "NativeLogin" function.
CefRefPtr<CefV8Value> func = CefV8Value::CreateFunction("NativeLogin", m_v8Handler); // Add the "NativeLogin" function to the "window" object.
object->SetValue("NativeLogin", func, V8_PROPERTY_ATTRIBUTE_NONE);
} void CCefBrowserApp::OnWebKitInitialized()
{
std::string app_code =
"var app;"
"if (!app)"
" app = {};"
"(function() {"
" app.GetId = function() {"
" native function GetId();"
" return GetId();"
" };"
"})();"; // Registered Javascript Function, which will be called by Cpp
" app.registerJavascriptFunction = function(name,callback) {"
" native function registerJavascriptFunction();"
" return registerJavascriptFunction(name,callback);"
" };" "})();"; CefRegisterExtension("v8/app", app_code, m_v8Handler);//第一个参数不能为空,否则报错,这个名字可以自定义
} 注:CefRegisterExtension的注释
// Example JavaScript extension code:
// <pre>
// // create the 'example' global object if it doesn't already exist.
// if (!example)
// example = {};
// // create the 'example.test' global object if it doesn't already exist.
// if (!example.test)
// example.test = {};
// (function() {
// // Define the function 'example.test.myfunction'.
// example.test.myfunction = function() {
// // Call CefV8Handler::Execute() with the function name 'MyFunction'
// // and no arguments.
// native function MyFunction();
// return MyFunction();
// };
// // Define the getter function for parameter 'example.test.myparam'.
// example.test.__defineGetter__('myparam', function() {
// // Call CefV8Handler::Execute() with the function name 'GetMyParam'
// // and no arguments.
// native function GetMyParam();
// return GetMyParam();
// });
// // Define the setter function for parameter 'example.test.myparam'.
// example.test.__defineSetter__('myparam', function(b) {
// // Call CefV8Handler::Execute() with the function name 'SetMyParam'
// // and a single argument.
// native function SetMyParam();
// if(b) SetMyParam(b);
// });
//
// // Extension definitions can also contain normal JavaScript variables
// // and functions.
// var myint = 0;
// example.test.increment = function() {
// myint += 1;
// return myint;
// };
// })();
// </pre>
// Example usage in the page:
// <pre>
// // Call the function.
// example.test.myfunction();
// // Set the parameter.
// example.test.myparam = value;
// // Get the parameter.
// value = example.test.myparam;
// // Call another function.
// example.test.increment();
// </pre>
///
void CCefBrowserApp::OnContextReleased(CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame, CefRefPtr<CefV8Context> context)
{
m_v8Handler = nullptr;
}
OnContextCreated给window对象绑定了一个NativeLogin函数,这个函数将由ClientV8Handler类来处理,当HTML中的JS代码调用window.NativeLogin时,ClientV8Handler的Execute方法会被调用。
OnWebKitInitialized注册了一个名为app的JS扩展,在这个扩展里为app定义了GetId方法,app.GetId内部调用了native版本的GetId()。HTML中的JS代码可能如下:
alert(app.GetId());
当浏览器执行上面的代码时,CCEFV8HandlerEx的Execute方法会被调用,现在来看CCEFV8HandlerEx的实现
.h
#ifndef _CEFV8HANDLEREX_H_
#define _CEFV8HANDLEREX_H_ #include "include/cef_v8.h" class CCEFV8HandlerEx : public CefV8Handler {
public:
CCEFV8HandlerEx(); ~CCEFV8HandlerEx();
public:
virtual bool Execute(const CefString& name, CefRefPtr<CefV8Value> object, const CefV8ValueList& arguments, CefRefPtr<CefV8Value>& retval, CefString& exception) override;
private:
// Map of message callbacks.
typedef std::map<std::pair<std::string, int>, std::pair<CefRefPtr<CefV8Context>, CefRefPtr<CefV8Value> > >CallbackMap;
CallbackMap callback_map_; protected:
IMPLEMENT_REFCOUNTING(CCEFV8HandlerEx);
};
#endif//_CEFV8HANDLEREX_H_
.cpp
#include "CEFV8HandlerEx.h"
#include "stdafx.h"
#include <strsafe.h> CCEFV8HandlerEx::CCEFV8HandlerEx()
{ } CCEFV8HandlerEx::~CCEFV8HandlerEx()
{
// Remove any JavaScript callbacks registered for the context that has been released.
if (!callback_map_.empty()) {
CallbackMap::iterator it = callback_map_.begin();
for (; it != callback_map_.end();) {
if (it->second.first->IsSame(it->second.first))
callback_map_.erase(it++);
else
++it;
}
}
} bool CCEFV8HandlerEx::Execute(const CefString& name /*JavaScript调用的C++方法名字*/, CefRefPtr<CefV8Value> object /*JavaScript调用者对象*/, const CefV8ValueList& arguments /*JavaScript传递的参数*/, CefRefPtr<CefV8Value>& retval /*返回给JS的值设置给这个对象*/, CefString& exception/*通知异常信息给JavaScript*/)
{
if (name == "NativeLogin")
{//Window Binding
if (arguments.size() == )
{
CefString strUser = arguments.at()->GetStringValue();
CefString strPassword = arguments.at()->GetStringValue(); //TODO: doSomething() in native way CefRefPtr<CefProcessMessage> msg = CefProcessMessage::Create("login_msg"); // Retrieve the argument list object.
CefRefPtr<CefListValue> args = msg->GetArgumentList(); // Populate the argument values.
args->SetSize();
args->SetString(, strUser);
args->SetString(, strPassword); // Send the process message to the browser process.
CefV8Context::GetCurrentContext()->GetBrowser()->SendProcessMessage(PID_BROWSER, msg); retval = CefV8Value::CreateInt();//函数的返回值 我们可以拿这个返回值做判断或者其他操作
//var result = window.NativeLogin(document.getElementById("userName").value, document.getElementById("password").value);
//document.getElementById("text").innerHTML = result
}
else
{
retval = CefV8Value::CreateInt();
}
return true;
}
else if (name == "GetId")
{//JS Extensions
if (arguments.size() == )
{
// execute javascript
// just for test
CefRefPtr<CefFrame> frame = CefV8Context::GetCurrentContext()->GetBrowser()->GetMainFrame();
frame->ExecuteJavaScript("alert('Hello, I came from native world.')", frame->GetURL(), ); // return to JS
retval = CefV8Value::CreateString("");
return true;
}
}
// Function does not exist.
return false;
}
在Browser进程中接受Render进程发过来的消息
重写 virtual bool OnProcessMessageReceived(CefRefPtr<CefBrowser> browser, CefProcessId source_process,CefRefPtr<CefProcessMessage> message);这个虚函数
我把C++函数都写在了窗口类中,所以我对CCefBrowserEventHandler做了修改,把窗口指针传到Browser中,方便调用
.h
#ifndef _CEFBROWSEREVENTHANDLER_H_
#define _CEFBROWSEREVENTHANDLER_H_
#include "include/cef_client.h"
#include "include/base/cef_lock.h" //线程安全 class CMainFrameWnd; class CCefBrowserEventHandler
: public CefClient
, public CefDisplayHandler // 显示变化事件
, public CefLoadHandler // 加载错误事件
, public CefLifeSpanHandler // 声明周期事件
//, public CefContextMenuHandler // 上下文菜单事件
//, public CefDialogHandler // 对话框事件
//, public CefDownloadHandler // 下载事件
//, public CefDragHandler // 拖拽事件
//, public CefFindHandler // 查找事件
//, public ...
{
public:
CCefBrowserEventHandler(CMainFrameWnd* pMainFrame); virtual ~CCefBrowserEventHandler(); public:
// CefClient 事件处理器,如果没有对应处理器则默认使用内部处理器
virtual CefRefPtr<CefDisplayHandler> GetDisplayHandler() OVERRIDE;
virtual CefRefPtr<CefLifeSpanHandler> GetLifeSpanHandler() OVERRIDE;
virtual CefRefPtr<CefLoadHandler> GetLoadHandler() OVERRIDE; public:
// display handler method
virtual void OnTitleChange(CefRefPtr<CefBrowser> browser, const CefString& title) OVERRIDE; public:
// load handler method
virtual void OnLoadError(CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame,
ErrorCode errorCode, const CefString& errorText, const CefString& failedUrl) OVERRIDE; public:
// display handler meethod
virtual void OnAfterCreated(CefRefPtr<CefBrowser> browser) OVERRIDE;
virtual bool DoClose(CefRefPtr<CefBrowser> browser) OVERRIDE;
virtual void OnBeforeClose(CefRefPtr<CefBrowser> browser) OVERRIDE; virtual bool OnProcessMessageReceived(CefRefPtr<CefBrowser> browser,
CefProcessId source_process,
CefRefPtr<CefProcessMessage> message); bool IsClosing() const { return m_bIsClosing; } CefRefPtr<CefBrowser> GetBrowser(){return m_Browser;} protected: CefRefPtr<CefBrowser> m_Browser; bool m_bIsClosing; CMainFrameWnd* m_pMainWnd; IMPLEMENT_REFCOUNTING(CCefBrowserEventHandler);
//由于CEF采用多线程架构,有必要使用锁和闭包来保证在多不同线程安全的传递数据。IMPLEMENT_LOCKING定义提供了Lock()和Unlock()方法以及AutoLock对象来保证不同代码块同步访问
IMPLEMENT_LOCKING(CCefBrowserEventHandler);//必须包含#include "include/base/cef_lock.h"
}; #endif//_CEFBROWSEREVENTHANDLER_H_
.cpp
#include "CefBrowserEventHandler.h"
#include "stdafx.h"
#include <sstream>
#include <string>
#include "include/cef_app.h"
#include "include/wrapper/cef_closure_task.h"
#include "include/wrapper/cef_helpers.h"
#include "MainFrameWnd.h" CCefBrowserEventHandler::CCefBrowserEventHandler(CMainFrameWnd* pMainFrame)
:m_bIsClosing(false)
,m_pMainWnd(pMainFrame)
{ } CCefBrowserEventHandler::~CCefBrowserEventHandler()
{ } CefRefPtr<CefDisplayHandler> CCefBrowserEventHandler::GetDisplayHandler()
{
return this;
} CefRefPtr<CefLifeSpanHandler> CCefBrowserEventHandler::GetLifeSpanHandler()
{
return this;
} CefRefPtr<CefLoadHandler> CCefBrowserEventHandler::GetLoadHandler()
{
return this;
} void CCefBrowserEventHandler::OnTitleChange(CefRefPtr<CefBrowser> browser, const CefString& title)
{ } void CCefBrowserEventHandler::OnLoadError(CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame, ErrorCode errorCode,
const CefString& errorText, const CefString& failedUrl)
{
CEF_REQUIRE_UI_THREAD();
if (ERR_ABORTED == errorCode)
return ; std::stringstream ss;
ss << "<html><body bgcolor=\"white\">"
"<h2>Failed to load URL " << std::string(failedUrl) <<
" with error " << std::string(errorText) << " (" << errorCode <<
").</h2></body></html>";
frame->LoadString(ss.str(), failedUrl);
} void CCefBrowserEventHandler::OnAfterCreated(CefRefPtr<CefBrowser> browser)
{
CEF_REQUIRE_UI_THREAD(); //base::AutoLock lock_scope(lock_); AutoLock lock_scope(this); m_Browser = browser; } bool CCefBrowserEventHandler::DoClose(CefRefPtr<CefBrowser> browser)
{
CEF_REQUIRE_UI_THREAD(); //base::AutoLock lock_scope(lock_);
AutoLock lock_scope(this); if(m_Browser)
{
// Set a flag to indicate that the window close should be allowed.
m_bIsClosing = true;
} return false;
} void CCefBrowserEventHandler::OnBeforeClose(CefRefPtr<CefBrowser> browser)
{
CEF_REQUIRE_UI_THREAD(); //base::AutoLock lock_scope(lock_);
AutoLock lock_scope(this); if(m_Browser->IsSame(browser))
m_Browser = NULL;
} bool CCefBrowserEventHandler::OnProcessMessageReceived(CefRefPtr<CefBrowser> browser,
CefProcessId source_process,
CefRefPtr<CefProcessMessage> message)
{
const std::string& messageName = message->GetName();
if (messageName == "login_msg")
{
// extract message
CefRefPtr<CefListValue> args = message->GetArgumentList();
CefString strUser = args->GetString();
CefString strPassword = args->GetString(); m_pMainWnd->CEFLoginJsCallCPP(strUser,strPassword);//窗口类的成员函数 //如果函数有返回值也可以通过向Render发送消息传递
//send reply to render process
CefRefPtr<CefProcessMessage> outMsg = CefProcessMessage::Create("login_reply"); // Retrieve the argument list object.
CefRefPtr<CefListValue> replyArgs = outMsg->GetArgumentList(); // Populate the argument values.
replyArgs->SetSize();
replyArgs->SetInt(, ); // Send the process message to the renderer process.
browser->SendProcessMessage(PID_RENDERER, outMsg); return true;
} return false;
}
Browser进程处理完后向Render进程发了消息,The render process receives the IPC message处理
.h
#ifndef _CEFBROWSERAPP_H_
#define _CEFBROWSERAPP_H_
#include "include/cef_app.h"
#include "CEFV8HandlerEx.h" class CCefBrowserApp
: public CefApp
, public CefBrowserProcessHandler
, public CefRenderProcessHandler
{
public:
CCefBrowserApp(); virtual ~CCefBrowserApp(); public:
virtual CefRefPtr<CefBrowserProcessHandler> GetBrowserProcessHandler()OVERRIDE { return this; }; public:
// CefBrowserProcessHandler methods:
virtual void OnContextInitialized(); //CefRenderProcessHandler methods
virtual void OnWebKitInitialized(); CefRefPtr<CefRenderProcessHandler> GetRenderProcessHandler() OVERRIDE{ return this; } virtual void OnContextCreated(CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame, CefRefPtr<CefV8Context> context); virtual void OnContextReleased(CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame, CefRefPtr<CefV8Context> context); //收消息
virtual bool OnProcessMessageReceived(CefRefPtr<CefBrowser> browser, CefProcessId source_process, CefRefPtr<CefProcessMessage> message); protected: CefRefPtr<CCEFV8HandlerEx> m_v8Handler; IMPLEMENT_REFCOUNTING(CCefBrowserApp);
};
#endif //_CEFBROWSERAPP_H_
.cpp
#include "CefBrowserApp.h"
#include "stdafx.h" CCefBrowserApp::CCefBrowserApp()
:m_v8Handler(new CCEFV8HandlerEx)
{
} CCefBrowserApp::~CCefBrowserApp()
{
} void CCefBrowserApp::OnContextInitialized()
{
// do nothing here, because we will create browser in my own dialog
} void CCefBrowserApp::OnContextCreated(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
CefRefPtr<CefV8Context> context)
{
// Retrieve the context's window object.
CefRefPtr<CefV8Value> object = context->GetGlobal(); // Create the "NativeLogin" function.
CefRefPtr<CefV8Value> func = CefV8Value::CreateFunction("NativeLogin", m_v8Handler);//第一个参数和SetValue参数保持一致,否则无法调用 // Add the "NativeLogin" function to the "window" object.
object->SetValue("NativeLogin", func, V8_PROPERTY_ATTRIBUTE_NONE); // Add the "register" function to the "window" object.
object->SetValue("register",CefV8Value::CreateFunction("register", m_v8Handler),V8_PROPERTY_ATTRIBUTE_NONE);
} void CCefBrowserApp::OnWebKitInitialized()
{
std::string app_code =
"var app;"
"if (!app)"
" app = {};"
"(function() {"
" app.GetId = function() {"
" native function GetId();"
" return GetId();"
" };"
"})();"; // Registered Javascript Function, which will be called by Cpp
" app.registerJavascriptFunction = function(name,callback) {"
" native function registerJavascriptFunction();"
" return registerJavascriptFunction(name,callback);"
" };" "})();"; CefRegisterExtension("v8/app", app_code, m_v8Handler);//第一个参数不能为空
} void CCefBrowserApp::OnContextReleased(CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame, CefRefPtr<CefV8Context> context)
{
m_v8Handler = nullptr;
} bool CCefBrowserApp::OnProcessMessageReceived(CefRefPtr<CefBrowser> browser,CefProcessId source_process,CefRefPtr<CefProcessMessage> message)
{
const std::string& messageName = message->GetName();
if (messageName == "login_reply")
{
// extract message
CefRefPtr<CefListValue> args = message->GetArgumentList();
bool status = args->GetBool(); CefRefPtr<CefFrame> frame = browser->GetMainFrame(); if (status)
{
frame->ExecuteJavaScript("IsSuccess();", frame->GetURL(), );
} return true;
} return false;
}
2.JS CallBack
在OnContextCreated()函数中给window绑定函数
// Create the "register" function.
CefRefPtr<CefV8Value> func = CefV8Value::CreateFunction("register", m_v8Handler);//第一个参数和SetValue参数保持一致,否则无法调用 // Add the "register" function to the "window" object.
object->SetValue("register", func, V8_PROPERTY_ATTRIBUTE_NONE);
在Exectue()函数中处理
else if (name == "register")
{
if (arguments.size() == && arguments[]->IsFunction())
{
CefRefPtr<CefV8Value> callback_func_ = arguments[];
CefRefPtr<CefV8Context> callback_context_ = CefV8Context::GetCurrentContext(); callback_func_->ExecuteFunction(NULL, arguments);//执行回调函数 return true;
}
}
在HTML的JavaScript里这样写
function myFunc()
{
// do something in JS.
alert("callback");
} //js CALLback
function CallBack()
{
window.register(myFunc);
}
3.C++ 调用 JS
C++调用JS函数相对简单多了,因为CEF有接口可以直接使用CefFrame::ExecuteJavaScript,看看注释:
///
// Execute a string of JavaScript code in this frame. The |script_url|
// parameter is the URL where the script in question can be found, if any.
// The renderer may request this URL to show the developer the source of the
// error. The |start_line| parameter is the base line number to use for error
// reporting.
///
/*--cef(optional_param=script_url)--*/
virtual void ExecuteJavaScript(const CefString& code,
const CefString& script_url,
int start_line) =;
首先需要获取到我们的浏览器里的主框架对象,code是JS函数和传入参数的字符串,URL可以直接忽略。
CefRefPtr<CefFrame> frame = m_handler->GetBrowser()->GetMainFrame(); m_handler是我们自己定义的Handler对象 /C++ 调用js方法
//frame->ExecuteJavaScript(L"Test();",frame->GetURL(),0);//提示框
//frame->ExecuteJavaScript(L"ModifyValue();",frame->GetURL(),0);//无参数函数
frame->ExecuteJavaScript(L"ModifyValue('巴萨牛逼');",frame->GetURL(),);//有参数函数
9 如果参数是可变的,可以这样
CString strJsCode;
strJsCode.Format(L"setInstallStatus('%s','%s','%d');", lpData->strId.c_str(), strStatus, nPercent);
其中setInstallStatus是js函数,它有三个参数
我在HMTL里写的
function Test()
{
alert("js被C++非礼了");
} function ModifyValue( arr)
{
//document.getElementById("text").innerHTML = "被修改了"; alert(arr);
document.getElementById("text").innerHTML = arr;
}
Duilib嵌入CEF以及JavaScript与C++交互的更多相关文章
- CEF中JavaScript与C++交互
在CEF里,JS和Native(C/C++)代码能够非常方便的交互,这里https://bitbucket.org/chromiumembedded/cef/wiki/JavaScriptIntegr ...
- Duilib嵌入CEF出现窗口显示不正常
参考资料:https://www.aliyun.com/zixun/wenji/1247250.html 转载:https://www.cnblogs.com/gongxijun/p/4857977. ...
- Duilib嵌入CEF禁止浏览器响应拖拽事件
转载:http://blog.csdn.net/liuyan20092009/article/details/53819473 转载:https://blog.csdn.net/u012778714( ...
- iOS中JavaScript和OC交互
转载自:http://www.devzeng.com/blog/ios-uiwebview-interaction-with-javascript.html 还可参考的文章:http://blog.c ...
- jQuery基础与JavaScript与CSS交互-第五章
目录 JavaScript框架种类及其优缺点 jQuery库 jQuery对象$ 掌握基本选择器 掌握过滤选择器 掌握表单选择器 RIA技术 常见的RIA技术 Ajax Sliverlight Fle ...
- 在android中实现webview与javascript之间的交互(转)
参见“在android中实现webview与javascript之间的交互”
- Hybrid App: 对比UIWebView和WebKit实现JavaScript与Native交互
一.简介 在前面一篇文章中讲到过实现JavaScript与Native交互的方式有一种就是使用原生内嵌webView.在iOS8之前,开发者只能使用苹果提供的UIWebView类来加载URL或者HTM ...
- Qt和JavaScript使用QWebChannel交互一——和Qt内嵌网页交互
Qt和JavaScript使用QWebChannel交互一--和Qt内嵌网页交互 目录 Qt和JavaScript使用QWebChannel交互一--和Qt内嵌网页交互 前言 一.效果 二.实现过程 ...
- iOS中JavaScript和OC交互 --by 胡 xu
在iOS开发中很多时候我们会和UIWebView打交道,目前国内的很多应用都采用了UIWebView的混合编程技术,最常见的是微信公众号的内容页面.前段时间在做微信公众平台相关的开发,发现很多应用场景 ...
随机推荐
- asp.net mvc中ViewData、ViewBag和TempData的详解
一.ViewData和ViewBag 1.ViewData和ViewBag都是从Action向View传递数据的方式,当然还有其他方式如向View传递Model. 2.ViewData页面查询数据时需 ...
- find命令的拾遗
find -maxdepth 1 -regextype posix-extended -type f -regex "\./${name}[-\.].*\.(gz|bz2|tgz|zip|t ...
- python Gunicorn
1. 简介 Gunicorn(Green Unicorn)是给Unix用的WSGI HTTP 服务器,它与不同的web框架是非常兼容的.易安装.轻.速度快. 2. 示例代码1 def app(envi ...
- asp.net 自带的缓存
本文导读:在.NET运用中经常用到缓存(Cache)对象.有HttpContext.Current.Cache以及HttpRuntime.Cache,HttpRuntime.Cache是应用程序级别的 ...
- Node.js 安装与配置
引言: JavaScript是一种运行在浏览器的脚本,它简单,轻巧,易于编辑,这种脚本通常用于浏览器的前端编程,但是一位开发者Ryan有一天发现这种前端式的脚本语言可以运行在服务器上的时候,一场席卷全 ...
- MWeb for iOS 测试版介绍
目前已开始第二次测试:MWeb for iOS 版本发布说明,更新至第二次测试版本  上图为 MWeb for iOS 的图标,再次感谢 @Producter http://weibo.com/u/ ...
- linux下JsonServer启动
1:进入到JsonServer run.sh目录下; 2:执行"export PATH=.:$PATH"; 3:执行"run.sh start"; 这样便把Js ...
- hbuilder的使用
今天在群里看群友提及了hbuilder,下载试了下,发现确实会有些代码敲起来方便多了.也帮助我自己发现uft8和保存的时候选择字符重要,不然乱码,很窝心.
- python学习笔记之迭代器和函数(第三天)
一.collection系列: 1.counter计数器 如果counter(dict)是对字典的一个补充,如果counter(list)则是对列表的补充,初步测试对字典的值进行排序. ####### ...
- window7下安装第三方包报错及解决
window7 64位下安装第三方包,,比如安装yaml的exe执行文件,会 报错及解决:python version 2.7(3.4) required,which was not found in ...