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



我使用的是ng样板,必须根据用户配置增加在生产中使用不同模板的可能性。

.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"

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

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;
        });
    }
})

我不会将其保留在服务中,因为服务将是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';
        }
      }
    }
  });
})

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

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

我建议使用$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将直接从script标记中加载它。

基于相同的原理,我有不同的方法

除了你不必自己用$http请求视图。

所以你可以让ui路由器来处理这个部分。

当您有一个复杂的视图体系结构时,这会更容易。

.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);
                }
            }
        })

最新更新