Bootstrap.js 在 Polymer 组件中不起作用

Posted

技术标签:

【中文标题】Bootstrap.js 在 Polymer 组件中不起作用【英文标题】:Bootstrap.js not working in Polymer components 【发布时间】:2013-08-23 11:34:20 【问题描述】:

我目前正在将我们当前的 Dart Web UI 项目转换为 Polymer.dart。我们将 Bootstrap 3 用于前端样式和许多 Web 动画(例如下拉菜单、模式、工具提示)。

然而,在我将一个 Web UI 组件翻译成 Polymer 后,所有的 Bootstrap javascript 都停止了对子组件的工作,因为它现在被封装在 ShadowDOM 中。要从 Dart 访问 ShadowDOM 中的元素,我必须使用 shadowRoot 字段,而从 Chrome 中的 JavaScript 我必须使用 webkitShadowRoot 属性,但我仍然无法让单个下拉菜单正常工作。

首先,在 bootstrap 中调用 dropdown('toggle') API 后,下拉菜单出现但永远不会消失。此外,似乎不可能检测到单击事件触发了哪个链接,因为该事件是在窗口级别触发的。这意味着我找不到要显示的下拉菜单。

有人有同时使用 twitter-bootstrap 和 Polymer 的经验吗?

【问题讨论】:

【参考方案1】:

您的问题是关于 Polymer.dart 端口的,但也适用于 Polymer.js 开发人员 :)

正如您所指出的,问题出在 Bootstrap 的 JS 上。它不知道 ShadowDOM 并尝试使用全局选择器从 DOM 中获取节点。例如,在 bootstrap-carousel.js 中,我看到如下内容:

$(document).on('click.carousel.data-api', ...', function (e)  ...);

我们之前探索过在 Polymer 中使用 Bootstrap 组件: https://github.com/Polymer/more-elements/tree/stable/Bootstrap

你最感兴趣的是<bs-accordion-item> (Demo)

这个过程基本上是将 Bootstrap 的东西包装在一个自定义元素中并调用它们的 API。

对于 CSS:如果您将其样式表包含在您的元素中,通常应该可以正常工作:

<polymer-element name="my-element">
  <template>
    <link rel="stylesheet" href="bootstrap.css">
    ...
  </template>
  <script>...</script>
</polymer-element>

请记住,如果 bootstrap.css 来自 CDN,则需要启用 CORS 才能使 polyfill 正常工作。当原生 html Imports 登陆时,这个要求就消失了。

【讨论】:

感谢埃比德尔!我将进行一些实验,看看是否可以运行 dart 版本。 顺便说一句,stable 分支中的演示似乎不适用于 Linux 中的 chrome 和 firefox,但是 master 分支中的演示可以。 我遇到了类似的问题,***.com/questions/18261596/… -- 让这个工作的关键点是 a) 从本地位置加载引导 css 文件,b) 通过代码应用作者样式,而不是标记. 上面提供的两个链接似乎已经过时了。这是 repo,任何人都在看:github.com/PolymerLabs/Bootstrap 如果我有多个需要以这种方式引导的组件怎么办,这不是一个巨大的冗余吗?【参考方案2】:

通过将 lightdom 属性添加到它们的定义中,我设法让 bootstrap.js 为我的聚合物组件工作。

<polymer-element name="my-element-with-bootstrap-js" lightdom 
apply-author-styles> 
<template>
<div>fancy template markup here</div>
</template> 
<script type="application/dart" src="my-element-with-bootstrap-js.dart"></script> 
</polymer-element>

宿主 HTML 可能如下所示:

<!DOCTYPE html>
<html>
<head>
<title>Unarin</title>
<meta name="viewport"
  content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />


<link rel="import" href="elements/my-element-with-bootstrap-js.html">

<script type="application/dart">export 'package:polymer/init.dart';</script>
<script src="packages/browser/dart.js" type="text/javascript"></script>

<link rel="stylesheet"
  href="//netdna.bootstrapcdn.com/bootstrap/3.0.2/css/bootstrap.min.css">
<script
  src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"
  type="text/javascript"></script>
<script
  src="//netdna.bootstrapcdn.com/bootstrap/3.0.2/js/bootstrap.min.js"
  type="text/javascript"></script>
</head>

<body>
  <my-element-with-bootstrap-js></my-element-with-bootstrap-js>
</body>
</html>

请注意:使用 lightdom 属性会将您的组件从 shadow DOM 替换为 light DOM,这可能会导致组件的样式与全局上下文的现有样式发生冲突。

相关讨论:https://groups.google.com/a/dartlang.org/forum/#!topic/web-ui/ps6b9wlg1Vk

根据讨论,我不能 100% 确定 lightdom 修改器是否会保持为聚合物组件实现此类功能的标准方式。也许作者可以对此发表评论?

【讨论】:

【参考方案3】:

其他答案中指出的问题是影子dom。 Bootstrap 看不到那里的元素,因此不能发挥它的魔力。您可以像这样禁用 shadowdom 并应用作者样式:

import 'package:polymer/polymer.dart';
import 'dart:html';

@CustomTag('main-messages')
class MainMessagesElement extends PolymerElement 
  MainMessagesElement.created() : super.created();

  //This enables the styling via bootstrap.css
  bool get applyAuthorStyles => true;
  //This enables the bootstrap javascript to see the elements
  @override
  Node shadowFromTemplate(Element template) 
    var dom = instanceTemplate(template);
    append(dom);
    shadowRootReady(this, template);
    return null; // no shadow here, it's all bright and shiny
     

您还需要删除所有父元素的 shadowdom。

警告:您将通过使用 lightdom 来使用点击事件处理程序:(

【讨论】:

以上是关于Bootstrap.js 在 Polymer 组件中不起作用的主要内容,如果未能解决你的问题,请参考以下文章

是否可以将模块导入 Polymer 组件?

是否可以将输入函数传递给Polymer中的另一个组件

如何在`内部设置Polymer组件的响应宽度 `

Polymer CLI和require

使用Polymer 2.0的简单web组件:从下拉列表更新值不起作用

定义 Polymer Web 组件而不导入它们