在KnockoutJS和AngularJS之间传递变量

时间:2015-10-02 13:53:55

标签: angularjs knockout.js

  1. 我在我的SPA仪表板创建中使用Knockout。它的工作性很好。但我们需要在仪表板中添加越来越复杂的东西,因此我们计划在Angular中开发仪表板的剩余部分。

  2. 我的问题是如何将变量从knockout传递给Angular。我尝试使用set和get方法,但它并没有帮助我.. 3.所以,我试过这样,我想在ko函数中设置一个属性值,就像这样..

  3. <li id="setMgmtEnv">
      <a href='javascript:;' data-bind="click: setMgmtEnv">
        <span>Manage Orgs</span>
      </a>
    </li>
    
    ///////in Main JS file
    var x = document.getElementById("setMgmtEnv"); 
            x.setAttribute("value", "0");
        ////// In KO model
        self.setMgmtEnv =  function(){
                    x.setAttribute("value", "1");           
                }
        ///////// In Angular i am noticing the change variable like this
       $scope.$watch(function(load) {
        return $scope.toLoad = document.getElementById('setMgmtEnv').value;
    }, function(newValue, oldValue) {
        console.log("$scope.toLoad2 : " + $scope.toLoad);
        if ($scope.toLoad) {
            console.log("$scope.toLoad3 : " + $scope.toLoad);
            $http({
                method : 'GET',
                url : url
            }).success(function(data) {
                console.log(data);
            }).error(function(data) {
                alert("Failure message: " + JSON.stringify({
                    data : data
                }));
            });
        }}
    

1 个答案:

答案 0 :(得分:7)

在一个应用程序中混合使用KnockoutJS和AngularJS是一个很大的危险信号。请确保您了解自己正在做的事情,或者您可能最好在Angular中重写KO部分。

话虽如此,我可以尝试回答您提出的问题,但不是在您提供的代码段的背景下(非常不清楚)。

KO可以通过三种主要方式与Angular互动(这是您似乎要问的方向):

  1. 他们各自控制自己的DOM。 KO将&#34;通知&#34; Angular通过Javascript代码。这将是首选的情况。
  2. 他们各自控制自己的DOM。 KO将&#34;通知&#34; Angular通过影响Angular实际控制的一块DOM。
  3. 他们共享控制同一块DOM。 KO&#34;通知&#34; Angular是自动的,因为它会在变量发生变化时更新DOM,而Angular的双向绑定会选择它。
  4. 选项2和3是灾难的秘诀。他们可以完成,但是那很糟糕我会留下创建一个PoC作为读者的练习。

    留下选项1,在特定情况下实际上可能有用。要做到这一点,你需要这些成分:

    • 在Angular的范围内,对KO ViewModel的引用;
    • 订阅KO的ViewModel相关部分;
    • 调用$scope.$apply没有通知Angular KO订阅回调已经改变了范围。

    这是一个例子:

    &#13;
    &#13;
    var ViewModel = function() {
      this.name = ko.observable("");
    };
    
    var vm = new ViewModel();
    
    angular.module("demoApp", [])
      .controller("myCtrl", ["$scope", function($scope) {
        $scope.name = vm.name();
      
        vm.name.subscribe(function(newVal) {
          $scope.$apply(function() {
            $scope.name = newVal;
          });
        });
      }]);
    
    ko.applyBindings(vm, document.getElementById("knockoutArea"));
    &#13;
    div { margin: 5px; padding: 5px; border: 1px solid #edd; background-color: #fee; }
    &#13;
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
    
    <div id="knockoutArea">
      <strong>Knockout</strong><br>
      Type your name: <input data-bind="textInput: name">
    </div>
    
    <div id="angularArea" ng-app="demoApp" ng-controller="myCtrl">
      <strong>Angular</strong><br>
      We know your name is: <strong>{{ name }}</strong>
    </div>
    &#13;
    &#13;
    &#13;

    作为替代方案,鉴于Angular似乎是你前进的方式,你可能想要反转依赖。给KO一个对Angular的引用,然后制作#&#34; legacy&#34;部分代码调用Angular范围的更新。这会使您的KO代码变得更脏,但会使您未来的代码库更加清晰。