加载Ng-Repeat元素后运行的jQuery Swiper脚本

And*_*M16 15 jquery angularjs angularjs-directive angularjs-ng-repeat swiper

我正在使用AngularJS,jQuery,HTML,CSS和Bootstrap创建一个Web应用程序,我想从我的JSON中选择一些位于Apache2服务器中的图像链接并使用它们来在我的主页面中呈现这些图像.我也想像旋转木马一样刷它们.为了做到这一点,我正在尝试使用iDangero.us Swiper.

当我用3个分开的div选择我的图像时,我没有问题.我得到了我的图像然后我可以按照我想要的方式刷它们.我这样做如下所示:

main.html中:

<div ng-init="initGetRequestMain()">

  <div class="swiper-slide" ng-click="swipers()" 
              style="{{data.background1}}"></div>
  <div class="swiper-slide" ng-click="swipers()" 
              style="{{data.background2}}"></div>
  <div class="swiper-slide" ng-click="swipers()" 
              style="{{data.background3}}"></div>

   <script src="scripts/custom/main/swipers.js"></script>
</div>
Run Code Online (Sandbox Code Playgroud)

我使用Swiper从一个图像滑动到另一个图像,它似乎应该工作.这是一个jQuery插件,你可以在这个链接上看到一些演示.

Swipers.js:

angular.module('swipers', [])
       .controller('',[ 
        $(document).ready(function (){
           var swiper = new Swiper('.swiper-container',{
           direction: 'horizontal',
           pagination: '.swiper-pagination',
           paginationClickable: true
       })
})]);
Run Code Online (Sandbox Code Playgroud)

JSON:

"background1":"background-image: url(images/img1.jpg)",
"background2":"background-image: url(images/img2.jpg)",
"background3":"background-image: url(images/img3.jpg)"
Run Code Online (Sandbox Code Playgroud)

mainController.js:

  myApp.controller('MainController', ["$scope","$http",                
                  function($scope,$http){

      $scope.initGetRequestMain = function(){

       $http.get('http://localhost/main.json').success(function(data){

         $scope.data=data;
       })
      }
  }]);
Run Code Online (Sandbox Code Playgroud)

问题是,当我尝试使用ng-repeat而不是3个分开的div时,我再也看不到它们了,我的Swiper脚本在完全加载之前就会触发.我的控制台或JSON中没有错误(使用JSONLint验证).下面,我在两种情况下都添加了2个输出屏幕截图.

使用3个独立的div:

使用3个独立的div

不使用ng-repeat:

不使用ng-repeat

这是我尝试使ng-repeat工作保持与以前相同的控制器和相同的Swiper脚本的代码:

main.html中:

  <div ng-init="initGetRequestMain()">

       <div ng-repeat="slide in data.slides" isLoaded="">
           <div class="swiper-slide" style="{{slide.background}}" 
                       ng-click="swipers()"></div>
       </div>

    <script type="text/javascript-lazy" src="scripts/custom/main/swipers.js"></script>
  </div>
Run Code Online (Sandbox Code Playgroud)

mainJson.json:

"slides":[
            {"background":"background-image:url('images/img1.jpg')"},
            {"background":"background-image:url('images/img2.jpg')"},
            {"background":"background-image: url('images/img3.jpg')"}
],
Run Code Online (Sandbox Code Playgroud)

为了在触发脚本之前加载我的图像,我正在尝试使用2个自定义指令.

isLoaded告诉我何时ng-repeat加载最后一个元素并设置pageIsLoaded = true;:

myApp.directive('isLoaded', function (){

   return{
     scope:true,
     restrict: 'A', //Attribute type
     link: function (scope, elements, arguments){ 

        if (scope.$last === true) {
            scope.pageIsReady = true;
            console.log('page Is Ready!');
         }
     }   
   }
})
Run Code Online (Sandbox Code Playgroud)

gettingTheScript等待pageIsLoaded = true;并加载脚本:

myApp.directive('src', function (){

     return{
       scope:true,
       restrict: 'A', //Attribute type
       link: function (scope, elements, arguments){

            scope.$on(pageIsReady===true, function(){
                   if (attr.type === 'text/javascript-lazy'){

                       scope.scriptLink = arguments.src;
                    }
             })
         },
         replace: true, //replaces our element 
         template: '{{scriptLink}}'
       }
  })   
Run Code Online (Sandbox Code Playgroud)

他们似乎没有解决我的问题.console.log('page Is Ready!');在制作第一个时我也看不清楚.

我只是在加载页面后必须触发像Swiper这样的脚本以避免这些问题时遇到麻烦.我的图像似乎没有高度.我认为问题是由于ng-repeat在触发我的脚本之前没有完全加载.

我究竟做错了什么?有更好的解决方案吗?

Joe*_*ger 11

在开始讨论如何使用这些工作之前,大多数这些类型的jQuery插件都不能很好地处理角度,因为它们会修改角度不知道的DOM.

话虽这么说,诀窍是推迟jQuery插件的调用,直到Angular渲染DOM.

首先,将swiper插件放入指令中:

.directive('swiper', function($timeout) {
    return {
        link: function(scope, element, attr) {
            //Option 1 - on ng-repeat change notification
            scope.$on('content-changed', function() {
                new Swiper(element , {
                    direction: 'horizontal',
                    pagination: '.swiper-pagination',
                    paginationClickable: true);
            }
            //Option 2 - using $timeout
            $timeout(function(){
                new Swiper(element , {
                    direction: 'horizontal',
                    pagination: '.swiper-pagination',
                    paginationClickable: true);
            });

        }
    };
})
Run Code Online (Sandbox Code Playgroud)

对于选项1,您需要修改的isLoaded指令

myApp.directive('isLoaded', function (){

   return{
     scope:false, //don't need a new scope
     restrict: 'A', //Attribute type
     link: function (scope, elements, arguments){ 

        if (scope.$last) {
            scope.$emit('content-changed');
            console.log('page Is Ready!');
        }
     }   
   }
})
Run Code Online (Sandbox Code Playgroud)

最后,你的标记(注意从isLoaded到is-loaded的变化....这可能是你没有看到通知的原因).

<div ng-init="initGetRequestMain()" swiper>

   <div ng-repeat="slide in data.slides" is-loaded>
       <div class="swiper-slide" style="{{slide.background}}" 
                   ng-click="swipers()"></div>
   </div>
</div>
Run Code Online (Sandbox Code Playgroud)

如上所述,大多数执行轮播功能的jQuery插件都不能很好地处理对DOM(即新元素)的更改.即使有这两个选项,如果在首次渲染ng-repeat后更改模型,也可能会看到意外情况.但是,如果您的模型是静态的,这应该适合您.如果您的模型发生变化,那么您可能希望搜索更"有角度"的轮播指令.