14

您好,感谢您的阅读。

我有一个正在制作的有角度的应用程序,我偶然发现了一个问题。如此设置

index.html-

<html ng-app="myApp">
...
<div ng-view></div>
<div ng-include="'footer.html'"></div>
...
</html>

我不会费心把我的路线放在它非常简单的 /home 是显示 /home/index.html 等等......

/home/index.html(访问站点时的默认视图)

<div class="responsive-block1">
<div class="tweet-me">
    <h1> tweet me </h1>
</div>

<div class="twitter-box">
    <twitter-timeline></twitter-timeline>
</div>

推特时间线指令

directives.directive("twitterTimeline", function() {
return { 
     restrict: 'E',
     template: '<a class="twitter-timeline" href="https://twitter.com/NAME" data-widget-id="XXXXXXXXXXXXXX">Tweets by @NAME</a>',
     link: function(scope, element, attrs) {

    function run(){
        (!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0],p=/^http:/.test(d.location)?'http':'https';if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src=p+"://platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs"));
        console.log('run script');
    };

    run();


     }
   };
});

所以我刚刚使用来自 twitter 的标签创建了一个基本的 twitter 指令。但是当我将视图示例更改为 /blog 然后返回 /home 时,twitter 小部件根本不再呈现。

我也在使用 $anchorScroll ,如果我在页面上跳转到这个小部件也会消失。任何信息都会非常感谢。

4

6 回答 6

11

看到这篇文章:https ://dev.twitter.com/discussions/890

我认为您可以通过调用 twttr.widgets.load() 来重新渲染小部件。

如果您发现这不起作用,则需要将此代码包装到控制器中的 $timeout 中:

    controller('MyCtrl1', ['$scope', '$timeout', function ($scope, $timeout) {
            $timeout = twttr.widgets.load();
    }])
于 2014-03-13T21:11:59.087 回答
4

以 l33tname 爵士的回答为基础:

在服务声明中:

    angular.module('app.services', []).
      service('tweetWidgets', function() {

        this.loadAllWidgets = function() {

            /* widgets loader code you get when 
             * declaring you widget with Twitter 
             * this code is the same for all widgets 
             * so calling it once will reference whatever
             * widgets are active in the current ng-view */

            !function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0],p=/^http:/.test(d.location)?'http':'https';if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src=p+"://platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");
         };

         this.destroyAllWidgets = function() {
            var $ = function (id) { return document.getElementById(id); };
            var twitter = $('twitter-wjs');
            if (twitter != null)
                twitter.remove();
         };  
      });

然后在控制器声明中:

    angular.module('app.controllers', []).
      controller('view_1_Controller', tweetWidgets) {

         // load them all
         tweetWidgets.loadAllWidgets();

     }).

       controller('view_2_Controller', tweetWidgets) {

          // now destroy them :>
          tweetWidgets.destroyAllWidgets();

     });

现在,每当您离开视图#1 转到视图#2 时,视图#2 的控制器将删除与视图#1 关联的小部件,当您返回视图#1 时,小部件将被重新设置。

于 2014-05-14T17:16:19.530 回答
2

问题是当 Angular 切换视图时,最初插入的脚本标签并未从文档中删除。当我的 Twitter 时间线指令不在视图中时,我通过删除 Twitter 脚本元素在我自己的网站上修复了这个问题。请参阅下面的代码和注释。

 function (scope, el, attrs) {
     el.bind('$destroy', function() {
         var twitterScriptEl = angular.element('#twitter-wjs');
         twitterScriptEl.remove();
     });

     // function provided by Twitter that's been formatted for easier reading
     function (d, s, id) {
         var js, fjs = d.getElementsByTagName(s)[0], p = /^http:/.test(d.location) ? 'http' : 'https';

         // If the Twitter script element is already on the document this will not get called. On a regular webpage that gets reloaded this isn't a problem. Angular views are loaded dynamically.
         if (!d.getElementById(id)) {
             js = d.createElement(s);
             js.id = id;
             js.src = p + "://platform.twitter.com/widgets.js";
             js.parentNode.insertBefore(js, fjs);
         }
     }(document, "script", "twitter-wjs");        
 }
于 2014-03-06T18:10:37.767 回答
2

基本上这就是Loc Nguyen所说的。

因此,每次重新创建它时,都必须先将其删除。

var $ = function (id) { return document.getElementById(id); };
function loadTwitter() {!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0],p=/^http:/.test(d.location)?'http':'https';if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src=p+"://platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");}

var twitter = $('twitter-wjs');
twitter.remove();
loadTwitter(); 
于 2014-05-11T11:07:32.827 回答
2

@b1r3k 的回答没有问题:

把它放在你的控制器中:

$timeout(function () { twttr.widgets.load(); }, 500); 
于 2015-11-11T10:01:55.147 回答
0

对于那些试图twttr.widgets.load()在他们的控制器中加载的人,您很可能会收到twttr未在您的 UX 中的某个点定义的错误,因为在您的控制器实例化和引用时,加载 twitter 脚本的异步调用可能尚未完成twttr

所以我创造了这个TwitterService

.factory('TwitterService', ['$timeout', function ($timeout) {
    return {
        load: function () {
        if (typeof twttr === 'undefined') {
            (function() {
                !function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0],p=/^http:/.test(d.location)?'http':'https';if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src=p+'://platform.twitter.com/widgets.js';fjs.parentNode.insertBefore(js,fjs);}}(document, 'script', 'twitter-wjs');
            })();
        } else {
            $timeout = twttr.widgets.load();
        };
        }
    }
}])

然后TwitterService.load()在需要您的小部件的控制器内部调用。这工作得很好。它基本上只是检查twttw对象是否存在,如果存在,只需重新加载脚本......否则只需重新加载脚本。

不确定这是否是最好的实现,但似乎所有其他解决方案都有会引发错误的极端情况。我还没有找到一个有这种选择的。

于 2015-01-21T18:16:57.727 回答