如何在 nativescript 中从 js 注入自定义组件?

How do I inject a custom component from js in nativescript?

假设我创建了一个接受输入并设置标签来显示它的小组件。

app/components/testComponent/testComponent.xml:

<Label id="someLabel" loaded="onLoad"/>

app/components/testComponent/testComponent.js:

exports.onLoad = args => {
    const obj = args.object;

    const label = obj.getViewById('someLabel');
    label.text = obj.someString || 'no string given';
};

现在我可以在我的任何页面中使用这个组件

<Page xmlns="http://schemas.nativescript.org/tns.xsd"
      xmlns:testComponent="components/testComponent">
    <StackLayout>
        <testComponent:testComponent someString="hello {N}"/>
    </StackLayout>
</Page>

这似乎是官方的做法,而且行之有效。但是有没有办法只使用 javascript 在页面中注入这个组件?

其中 filepath 是一个脚本 - 甚至是一个 class 回调函数可以创建的实例。 这就像它在页面加载时加载并显示在大多数开发人员工具控制台中一样。

        var uuid='xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
             var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);
             return v.toString(16);
        });
             var url = filepath + "?" + uuid;//prevent caching - does not work with ajax setup
             try {
                    $.getScript(url, "callbackfunctionname('" + filepath + "')");//getScript callback seems broken so use own
             }
             catch (e) {
                    //error handle
             }

是的,声明式 UI(即 xml)实际上是一个构建系统,可以解析 xml 并生成 JS,因此您不必这样做。

因此,如果您想手动执行此操作,您可以单独保留组件代码,并将主屏幕代码更改为如下所示:

<Page xmlns="http://schemas.nativescript.org/tns.xsd" loaded="onLoad">
    <StackLayout id='sl'>

    </StackLayout>
</Page>

您会注意到的第一件事是我们为页面提供了一个加载事件,您必须在某个地方实际 运行 您的代码才能将您的组件附加到可视化树。我们做的第二件事是向 StackLayout 添加一个 id;这在技术上实际上并不需要——您可以导航 NS 树并找到合适的 StackLayout;但为了简单起见,添加一个 ID 会使它变得容易得多。


因此您页面中的 JS 代码将是:

var builder = require('ui/builder');
var fs = require('file-system');

exports.onLoad = function(args) {
  // Get our current Page that is being loaded
  var page = args.object;

  // Find our StackLayout
  var stackLayout = page.getViewById('sl');

  // Load our JS for the component
  var path = fs.knownFolders.currentApp().path;
  var componentJS = require(path + '/components/testComponent/testComponent.js');

  // Actually have the builder build the Component using the XML & JS.
  var component = builder.load(path + '/components/testComponent/testComponent.xml', componentJS);

  // And add our component to the visual tree
  stackLayout.addChild(component);
};

我相信,因为您在加载事件中添加了子组件,所以子组件中的页面加载事件将是 运行,但不要让我相信那个。如果不是,那么您可以在添加它的同时手动 运行 它...