dotnet项目使用Cefsharp与Js互相调用函数

1. 背景

最近在一个项目中使用 CefSharp 加载H5页面, 其中一些业务逻辑需要调用 Js 函数, 同时 Js 也会调用一些 native 函数:

这里我们使用官方的demo代码进行添加修改, 修改后的代码在此: DevWiki/CefSharp.MinimalExample - CefSharp.MinimalExample - DevWiki Gitea

2. Js调用 Native 函数

根据官方的说明, General Usage · cefsharp/CefSharp Wiki, 分为两步:

  1. 设置 启用 Js
  2. 注册一个 Class 给Js调用
//设置 启用 Js
Browser.BrowserSettings.Javascript = CefState.Enabled;
Browser.JavascriptObjectRepository.Settings.LegacyBindingEnabled = true;
//注册一个 Class 给Js调用
Browser.JavascriptObjectRepository.Register("script", new Script(), false, BindingOptions.DefaultBinder);

public class Script
{
    
    
    public string GetWindowName()
    {
    
    
        return "MainWindow";
    }

    public void PrintLog(string log)
    {
    
    
        Console.WriteLine($"H5 log:{
      
      log}");
    }
}

为了方便测试, 给 Browser 设置一下响应 F12 打开 DevTool:

Browser.WpfKeyboardHandler = new WebBrowserWpfKeyboardHandler(Browser);

public class WebBrowserWpfKeyboardHandler : WpfImeKeyboardHandler
    {
    
    
        public WebBrowserWpfKeyboardHandler(ChromiumWebBrowser owner) : base(owner)
        {
    
    
        }
        public override void HandleKeyPress(KeyEventArgs e)
        {
    
    
            base.HandleKeyPress(e);
            if (e.Key == Key.F12)
            {
    
    
                owner.ShowDevTools();
            }
        }
    }

运行后 , 按 F12, 打开控制台输入: script. 看看提示:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kwCxn2xc-1670731074318)(api/images/iGKYxVbEAHsw/202212102324686.png)]

可以看到 我们注册的函数, 这样Js就可以调用 native函数了.

还有一种方式是动态注册, 如下:

Browser.JavascriptObjectRepository.ResolveObject += JavascriptObjectRepositoryOnResolveObject;

private void JavascriptObjectRepositoryOnResolveObject(object sender, JavascriptBindingEventArgs e)
{
    
    
    var repo = e.ObjectRepository;
    if (e.ObjectName == "script")
    {
    
    
        repo.Register("script", new Script(), isAsync: true, options: BindingOptions.DefaultBinder);
    }
}

3. WPF调用Js函数

一般的网页都有有 alert() 这个函数, 就是弹出一个对话窗口, 按 F12 打开 devtool 切换到控制台, 输入函数然后回车, 结果如下图:

1670728613515.png

也可以传入一个参数, 显示提示消息: alert("test"):

1670728686336.png

那 如何在 项目中调用呢? 根据官方的文档: CefSharp中文帮助文档 · cefsharp/CefSharp Wiki

Browser.MainFrame.ExecuteJavaScriptAsync("alert()"); 
// 或者
Browser.ExecuteScriptAsync("alert()");

如果需要传入参数, 则可以直接使用字符串插值:

Browser.MainFrame.ExecuteJavaScriptAsync($"alert({message})"); 
// 或者
Browser.ExecuteScriptAsync($"alert({message})");

或者使用传入参数的方法:

object[] args = new object[2];
args[0] = JsArgs1Tb.Text;
args[1] = JsArgs2Tb.Text;
Browser.ExecuteScriptAsync("alert()", args);

如果你安装上述的代码调用带参数的Js 函数, 实际上无法按照你预想的执行!

如果你安装上述的代码调用带参数的Js 函数, 实际上无法按照你预想的执行!

如果你安装上述的代码调用带参数的Js 函数, 实际上无法按照你预想的执行!

重要的事情说三遍!

为何会出现上述问题呢? 这里需要看下 带参数的函数具体做了什么?

    public static void ExecuteScriptAsync(
      this IBrowser browser,
      string methodName,
      params object[] args)
    {
    
    
      string javascriptMethodWithArgs = WebBrowserExtensions.GetScriptForJavascriptMethodWithArgs(methodName, args);
      browser.ExecuteScriptAsync(javascriptMethodWithArgs);
    }

在这段代码中, 会先把 函数名称 和 函数参数进行拼接:

WebBrowserExtensions.GetScriptForJavascriptMethodWithArgs(methodName, args);

这里测试下 alert 函数与参数的拼接:

拼接后的结果会自动带上 () , 去除括号后再次测试:

弹窗如下:

在提示出现了我们的填写内容.

3. 总结

使用 Js 调用 native 函数:

  1. WebBrowser 设置启用 Js 功能
  2. 注册一个 class 给 Js 调用

使用 native 调用 js 函数:

  1. 如果是无参函数, 函数名需要带上: ()
  2. 如果是有参数函数, 要么调用时拼接好为完整的函数+参数, 要么调用时使用 WebBrowserExtensions.GetScriptForJavascriptMethodWithArgs 并且函数只写名称不带括号.

以上代码在: DevWiki/CefSharp.MinimalExample - CefSharp.MinimalExample - DevWiki Gitea

猜你喜欢

转载自blog.csdn.net/DevWiki/article/details/128273384