Ken*_*nne 13 unit-testing disqus angularjs single-page-application angularjs-directive
在单页面应用程序中使用Disqus的最佳方法是什么?我看到角度js docs已经成功实现了它.
目前我们的方法看起来就像我们的AngularJS应用程序,但它看起来不稳定,难以测试,并加载错误的线程ID(相同的线程几乎到处都加载).
'use strict';
angular.module('studentportalenApp.components')
.directive('disqusComponent',['$log', '$rootScope', function($log, $rootScope) {
var _initDisqus = function _initDisqus(attrs)
{
if(window.DISQUS) {
DISQUS.reset({
reload: true,
config: function () {
this.page.identifier = attrs.threadId;
this.disqus_container_id = 'disqus_thread';
this.page.url = attrs.permalinkUrl;
}
});
}
else
{
$log.error('window.DISQUS did not exist before directive was loaded.');
}
}
//Destroy DISQUS bindings just before route change, to properly dispose of listeners and frame (postMessage nullpointer exception)
$rootScope.$on('$routeChangeStart', function() {
if(window.DISQUS) {
DISQUS.reset();
}
});
var _linkFn = function link(scope, element, attrs) {
_initDisqus(attrs);
}
return {
replace: true,
template: '<div id="disqus_thread"></div>',
link: _linkFn
};
}]);
Run Code Online (Sandbox Code Playgroud)
我还想在我的AngularJS支持的博客上加入Disqus.我发现现有的解决方案有点笨拙所以我编写了自己的指令:
.directive('dirDisqus', function($window) {
return {
restrict: 'E',
scope: {
disqus_shortname: '@disqusShortname',
disqus_identifier: '@disqusIdentifier',
disqus_title: '@disqusTitle',
disqus_url: '@disqusUrl',
disqus_category_id: '@disqusCategoryId',
disqus_disable_mobile: '@disqusDisableMobile',
readyToBind: "@"
},
template: '<div id="disqus_thread"></div><a href="http://disqus.com" class="dsq-brlink">comments powered by <span class="logo-disqus">Disqus</span></a>',
link: function(scope) {
scope.$watch("readyToBind", function(isReady) {
// If the directive has been called without the 'ready-to-bind' attribute, we
// set the default to "true" so that Disqus will be loaded straight away.
if ( !angular.isDefined( isReady ) ) {
isReady = "true";
}
if (scope.$eval(isReady)) {
// put the config variables into separate global vars so that the Disqus script can see them
$window.disqus_shortname = scope.disqus_shortname;
$window.disqus_identifier = scope.disqus_identifier;
$window.disqus_title = scope.disqus_title;
$window.disqus_url = scope.disqus_url;
$window.disqus_category_id = scope.disqus_category_id;
$window.disqus_disable_mobile = scope.disqus_disable_mobile;
// get the remote Disqus script and insert it into the DOM
var dsq = document.createElement('script'); dsq.type = 'text/javascript'; dsq.async = true;
dsq.src = '//' + scope.disqus_shortname + '.disqus.com/embed.js';
(document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq);
}
});
}
};
});
Run Code Online (Sandbox Code Playgroud)
我认为,这种方法的主要优点是它可以保持简单.在您的应用程序中注册该指令后,您无需在JavaScript中编写任何JavaScript或设置任何配置值.所有配置都通过在指令标记中传递属性来处理,如下所示:
<dir-disqus disqus-shortname="YOUR_DISQUS_SHORTNAME"
disqus-identifier="{{ article.id }}"
disqus-title="{{ article.title }}"
...>
</dir-disqus>
Run Code Online (Sandbox Code Playgroud)
此外,您不需要更改index.html文件以包含Disqus .js文件 - 该指令将在准备好后动态加载它.这意味着所有额外的.js只会加载到实际使用Disqus指令的那些页面上.
只有当您的网站使用HTML5Mode时,上述内容才能正常运行,即您的网址中未使用"#".我正在更新GitHub上的代码,因此该指令在不使用HTML5Mode时会起作用,但是要警告您必须将hashPrefix设置为"!" 制作"hashbang"网址 - 例如www.mysite.com/#!/page/123.这是Disqus所施加的限制 - 请参阅http://help.disqus.com/customer/portal/articles/472107-using-disqus-on-ajax-sites