如何使用AngularJS模板进行A / B测试?

时间:2013-07-19 12:11:58

标签: angularjs ab-testing

我正在使用ng-boilerplate,并且必须根据用户配置添加在生产中使用不同模板的可能性。

.config(function config( $stateProvider ) {
 $stateProvider.state( 'demo', {
    url: '/demo',
    views: {
      "main": {
        controller: 'DemoCtrl',
        templateUrl: 'demo/demo.tpl.html'
      }
    }
  });
})

我目前的想法是使templateUrl动态

templateUrl: 'demo/demo'+userService.getTemplate()+'.tpl.html'

并拥有多个模板文件,例如:

  • demo.tpl.html(默认)
  • demo.b.tpl.html(版本b)
  • demo.c.tpl.html(版本c)

虽然userService函数确实提供了要使用的模板版本,例如“.B”

你同意吗?是否有更好/更容易解决这个问题的方法?

4 个答案:

答案 0 :(得分:11)

AngularJS标准$routeProvider可以接受templateUrl的功能。但是你不能将服务注入到这个函数中。

ui-routertemplateProvider参数,您可以在其中注入您想要的内容,您应该为远程模板案例返回类似的内容:

$stateProvider.state('demo', {
    templateProvider: function ($http, $templateCache, $stateParams, userService) {
        var url = 'demo/demo' + userService.getTemplate() + '.tpl.html';
        return $http.get(url, { cache: $templateCache }).then(function (response) {
            return response.data;
        });
    }
})

答案 1 :(得分:2)

我不会保留它,因为服务将是js文件的一部分。哪个是静态的(在正常情况下)

我将这样做,在html文件中我将把

window.abConfig = "defaultVersion";

在app.js中我会放

.config(function config( $stateProvider ) {
 $stateProvider.state( 'demo', {
    url: '/demo',
    views: {
      "main": {
        controller: 'DemoCtrl',
        templateUrl: function() {
          return 'demo/demo' + window.abConfig + '.tpl.html';
        }
      }
    }
  });
})

它的Hacky方式,但它让我可以灵活地决定在服务器级别向用户显示哪个版本。我可能需要在用户根据用户之前的活动下载内容之前编写逻辑,这是我无法从客户端javascript执行的。

答案 2 :(得分:1)

这可以使用标准角度来实现,你只需要从另一个角度看它!

我建议使用$templateCache。加载应用程序时,您可以使用所选版本的用户模板预填充$ template缓存。

您可以执行类似

的操作
$templateCache.put("page-header.html", '<h1>MyAwesomeStartup</h1><h2>Buy now!?!?!</h2>');

此外,如果您不反对这个想法,可以使用脚本标记语法将模板放入页面,其中id ==您在$ routeProvider中使用的templateURL。

<script type="text/ng-template" id="page-header.html">
  <h1>MyAwesomeStartup</h1><h2>Buy now!?!?!</h2>
</script>

并且ng将直接从脚本标记加载它。

答案 3 :(得分:0)

我基于相同的原则采用不同的方式

除非您不必使用$ http实际请求查看。

所以你可以让ui-router处理那个部分。

当您拥有复杂的视图架构时,这会更容易。

.state('public.index', {
            url: '/',
            views: {
                "": {
                    template: '<div ui-view="abTestDummyView"></div>',
                    controller: ['landing', '$http', function(landing, $http) {
                        alert('Showing AB Test Landing #' + landing);
                        // increment landing stats
                        $http.get('http://stats.domain.com', {landing: landing});
                    }],
                    controllerAs: 'landingCtrl',
                },
                "abTestDummyView@public.index": {
                    templateProvider: ['landing', function(landing) {
                        // inject a view based on its name
                        return "<div ui-view=\"ab" + landing + "\"></div>";
                    }]
                },
                "ab1@public.index": {
                    template: "INJECTED AB1"
                    // replace by templateUrl: "/real path/"
                },
                "ab2@public.index": {
                    template: "INJECTED AB2"
                    // replace by templateUrl: "/real path/"
                }
            },
            resolve: {
                landing: function() {
                    return Math.floor((Math.random() * 2) + 1);
                }
            }
        })