【问题标题】:Ember component rendered HTML isn't found by FB.XFBML.parse()FB.XFBML.parse() 找不到 Ember 组件呈现的 HTML
【发布时间】:2015-03-19 16:21:38
【问题描述】:

更新 1

我已将问题追溯到 FB.XFBML.parse() 使用的 html5Info 函数。它有一个条件。这是两个元素不同的布尔语句:element.getAttribute('fb-xfbml-state') 变为 "rendered"(真实)或 null(虚假),具体取决于处理的元素。

所以问题缩小到...

为什么我的 ember 组件的渲染 HTML 没有将其“fb-xfbml-state”设置为“渲染”,而模板中的静态 HTML 有?

更新 2

通过让我的 facebook 组件包含这样的 .setAttribute 调用来解决我的问题。

/* global FB */
import Ember from 'ember';

export default Ember.Component.extend({
    tagName: 'div',
    classNames: 'fb-share-button',
    attributeBindings: [
        'data-href',
        'data-layout',
        'data-action',
        'data-show-faces',
        'data-share'
    ],

    onDidInsertElement: function() {
        Ember.run.debounce(this, function() {
            console.log(document)
            _.forEach(document.getElementsByClassName('fb-share-button'), function(element) {
                element.setAttribute('fb-xfbml-state', 'rendered');
            });
            FB.XFBML.parse();
        }, 250);
    }.on('didInsertElement'),
});

更新 3

似乎组件生成了子节点,如document.getElementById('myComponentElementInTheDOM').childNodes,这些是组件生成的 HTML 和纯 HTML 之间的不同之处。 FB-SDK 有一个条件 IF 语句,它为没有子节点的纯 HTML 生成 true,而为组件生成的具有子节点的 HTML 生成 false,导致仅将纯 HTML 视为要呈现的目标。

问题...

我有一种情况,我使用 chrome 检查器检查 DOM,我发现两个相等的 html sn-ps:

<div id="ember403" class="ember-view fb-share-button" data-href="https://mypage.com" data-layout="button_count" data-action="like" data-show-faces="false" data-share="true"></div>
<div id="ember407" class="ember-view fb-share-button" data-href="https://mypage.com" data-layout="button_count" data-action="like" data-show-faces="false" data-share="true"></div>

其中一个以纯 HTML 格式放入路由把手文件中,另一个使用我制作的 Ember 组件呈现。页面加载完成后手动调用 FB.XFBML.parse() 只会找到一个。

有什么区别!?

我使用了 facebook SDK 的 debug.js 版本,当我调用 FB.XFBML.parse() 时,它会说:

XFBML Parsing Finish 2, 1 tags found

// Debug version: connect.facebook.net/en_US/all/debug.js
// Normal version: connect.facebook.net/en_US/sdk.js

但是……

如果我现在首先使用 chrome 检查器以某种非常简单的方式修改 DOM,比如添加一个新的空行。之后我可以再次调用FB.XFBML.parse() 并突然找到两个标签。

我不明白...

我可以怎样做才能让 FB.XFMBL.parse() 找到我的 ember 组件生成的 HTML,就像路由把手文件中的纯 HTML 生成的 HTML 一样?

我的路由模板生成相同的 HTML

{{social-facebook data-href="https://mypage.com" data-layout="button_count" data-action="like" data-show-faces="false" data-share="true"}}

<div id="ember407" class="ember-view fb-share-button" data-href="https://mypage.com" data-layout="button_count" data-action="like" data-show-faces="false" data-share="true"></div>

以上代码在chrome inspector中生成如下:

我的组件

/* global FB */
import Ember from 'ember';

export default Ember.Component.extend({
    tagName: 'div',
    classNames: 'fb-share-button',
    attributeBindings: [
        'data-href',
        'data-layout',
        'data-action',
        'data-show-faces',
        'data-share'
    ],

    onDidInsertElement: function() {
        Ember.run.schedule('afterRender', FB.XFBML.parse);
    }.on('didInsertElement'),
});

我的组件模板

{{yield}}

我的初始化器

/* global FB */
import ENV from '../config/environment';

export function initialize(container, application) {
    var debug = false;

    // Wait for Facebook to load before allowing the application
    // to fully boot. This prevents `ReferenceError: FB is not defined`
    application.deferReadiness();

    var fbAsyncInit = function() {
        console.log("SOCIAL DEBUG: fbAsyncInit invoked.");
        initFacebook(window.FB);
        application.advanceReadiness();
    };

    loadFacebookSDK(debug);
    window.fbAsyncInit = fbAsyncInit;
}

function initFacebook(FB) {
    console.log("SOCIAL DEBUG: FB.init invoked.", ENV.fbAppId, ENV.fbSDKVersion);
    FB.init({
        appId      : ENV.fbAppId,
        xfbml      : true,
        version    : ENV.fbSDKVersion
    });
}

function loadFacebookSDK(debug) {
    (function(d, s, id){
        console.log("SOCIAL DEBUG: Load facebook SDK code", d, s, id);
        var js, fjs = d.getElementsByTagName(s)[0];
        if (d.getElementById(id)) {return;}
        js = d.createElement(s); js.id = id;
        js.src = debug ? "//connect.facebook.net/en_US/all/debug.js" : "//connect.facebook.net/sv_SE/sdk.js";
        fjs.parentNode.insertBefore(js, fjs);
    }(document, 'script', 'facebook-jssdk'));
}

export default {
  name: 'social-facebook',
  initialize: initialize
};

【问题讨论】:

    标签: ember.js facebook-javascript-sdk


    【解决方案1】:

    这个组件修改就可以了

    此组件代码可用于解决由组件创建的隐藏子节点来处理数据绑定所引起的问题。由于我无法调整 ember 组件和 facebook sdk 的工作方式,因此该解决方案与我想象的一样接近完美。

    /* global FB */
    import Ember from 'ember';
    
    export default Ember.Component.extend({
        tagName: 'div',
        classNames: 'fb-share-button',
        attributeBindings: [
            'data-href',
            'data-layout',
            'data-action',
            'data-show-faces',
            'data-share'
        ],
    
        onDidInsertElement: function() {
            // This is needed to make the FB SDK accept the component rendered HTML even though child nodes due to databinding exists
            // To understand more about this, follow the code inside connect.facebook.net/en_US/all/debug.js
            // 1: Read up on the function FB.XFBML.parse, found by searching for: 'function parse(/*DOMElement*/ dom'
            // 2: Read up on the function html5Info, whos returnvalue will be affected, found by searching for: 'function html5Info('
            // 3: Notice the conditional inside html5Info containing the booleans below:
            //        element.childNodes.length === 0           --- supposed to evaluate to true, but isn't due to childNodes used for databinding
            //        element.getAttribute('fb-xfbml-state')    --- used to make sure that the conditional becomes true for the component
            document.getElementById(this.get('elementId')).setAttribute('fb-xfbml-state', 'rendered');
    
            // This makes FB-SDK render the HTML-stubs inserted by the ember components
            Ember.run.debounce(this, FB.XFBML.parse, 100);
        }.on('didInsertElement'),
    });
    

    供参考,这是我使用的相关初始化程序

    /* global FB */
    import ENV from '../config/environment';
    
    export function initialize(container, application) {
        var debug = true;
    
        // Wait for Facebook to load before allowing the application
        // to fully boot. This prevents `ReferenceError: FB is not defined`
        application.deferReadiness();
    
        var fbAsyncInit = function() {
            initFacebook(window.FB);
            application.advanceReadiness();
        };
    
        loadFacebookSDK(debug);
    
        window.fbAsyncInit = fbAsyncInit;
    }
    
    function initFacebook(FB) {
        FB.init({
            appId      : ENV.fbAppId,
            xfbml      : true,
            version    : ENV.fbSDKVersion
        });
    }
    
    function loadFacebookSDK(debug) {
        (function(d, s, id){
            var js, fjs = d.getElementsByTagName(s)[0];
            if (d.getElementById(id)) {return;}
            js = d.createElement(s); js.id = id;
            js.src = debug ? "//connect.facebook.net/en_US/all/debug.js" : "//connect.facebook.net/sv_SE/sdk.js";
            fjs.parentNode.insertBefore(js, fjs);
        }(document, 'script', 'facebook-jssdk'));
    }
    
    export default {
      name: 'social-facebook',
      initialize: initialize
    };
    

    以及如何使用组件的示例

    {{social-facebook data-href="https://yourwebpage.com" data-layout="button_count" data-action="like" data-show-faces="false" data-share="true"}}
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-09-14
      • 2018-08-16
      • 2018-10-21
      • 1970-01-01
      • 2015-10-19
      • 2018-08-03
      • 1970-01-01
      • 2020-04-25
      相关资源
      最近更新 更多