UWP支持使用Javascript来调用Windows Runtime接口。但是有一个问题,官方例子中Create a “Hello, world” app (JS)只适用于Visual Studio 2017。因为Visual Studio 2019在可创建的项目列表中移除了模板Blank App (Universal Windows) JavaScript

关于Visual Studio 2019为什么移除Blank App (Universal Windows) JavaScript,网上有一些讨论:

根据这条信息

You can build PWAs optimized for Windows using the tools provided in Visual Studio 2019. Support for WWAs is available in Visual Studio 2017 and not Visual Studio 2019.

上面的PWA指ProgressiveWebApp,WWA指WindowsWebApp。我觉得大体的问题是微软决定转而支持PWA这种标准的架构,而不是Cordorva这种基于Electron的混合架构(需要采用wwahost.exe)。

使用UWP的WebView

虽然没有了JS的UWP应用模板,但是还是可以在UWP的WebView中使用JS调用WinRT的API。打开VS2019,创建一个Blank App Universal Windows C#项目,取名HelloJS。

根据Call WinRT APIs from your PWA的指示,打开Package.appxmanifest文件,设置相应的Application Content URI Rules (ACURs)。具体的做法是在Content URIs面版上添加

  • URI:ms-appx-web:///hello.html
  • Rule:Include
  • WinRT Access: All

第二步是添加一个Text文件,会自动生成TextFile1.txt,将其重命名为hello.html,将差不多来自Create a “Hello, world” app (JS)的内容填入:

<!DOCTYPE html>
<html>

<head>
  <meta charset="utf-8" />
  <title>Hello World</title>
</head>

<body>
  <p>Click the button..</p>
  <button id="button">Hello world!</button>

<script language="javascript">
  // Your code here!

window.onload = function () {
    document.getElementById("button").onclick = function (evt) {
        sayHello()
    }
}


function sayHello() {
    var messageDialog = new Windows.UI.Popups.MessageDialog("Hello, world!", "Alert");
    messageDialog.showAsync();
}
</script>

</body>

</html>

保存完上述文件后,记得在Solution Explorer里面选中该文件,然后Alt+Enter编辑该文件的属性,将Item Type改为Copy File

接下来,只要打开MainPage.xaml,将里面的<Grid></Gride>换成:

   <WebView Source="ms-appx-web:///hello.html"/>

然后编译运行,就可以看到和Create a “Hello, world” app (JS)一样的HTML页面,有一个按键,点击以后会产生一个Alert。任务完成。

关于AllowForWeb

WinRT Access除了All以外,还可以设置成AddWebAllowedObject。但是AddWebAllowedObject有一个要求,那就是其API必须来自另外一个Windows Runtime Component(也就是另外一个DLL)。否则就会出错,参考UWP WebView Javascript “Object doesn’t support property or method”

文档中的说法是:

The object passed into AddWebAllowedObject(System.String,System.Object) must be imported from a Windows Runtime component that is separate from the app assembly. This is necessary for the AllowForWeb attribute to be property identified by the WebView security subsystem. If you use a class from your app project, AddWebAllowedObject(System.String,System.Object) does not work.

其他参考

(完)

更新2019-10-02,如何在VS2019 Debug Webview中的JS

官网上只有VS2017的指导:Debug a WebView control in a UWP App

在2019中,也可以做类似的操作,在项目的Debugging配置中,选择Script only,然后再启动调试。也可以不启动调试,但是以Script only的方式去attach目前进程。

ActivatableClass

(更新完)

2020-11-22(更新)