javascript - 如何在 ng-repeat 循环中分配一个 angularjs 事件监听器?

标签 javascript html css angularjs

我是 angularjs 的新手。我正在尝试创建一个照片库,其中初始页面是一张来自 twitter 和 instagram 的缩略图照片,使用 angularjs ng-repeat 循环创建。当用户将鼠标悬停在图像上时,图像会淡化并出现一个按钮供用户单击。我使用 ng-mouseenter 和 ng-mouseleave 创建了悬停效果。但出于某种原因,当我将鼠标悬停在图像上时,所有图像都会受到影响。只有我悬停的单个图像应该被定位。我不确定我做错了什么。请帮忙!代码如下。这里还有一个在线代码的链接: http://www.petermingione.com/my-demo/

<style>
        * {
            box-sizing: border-box;
            font-family: sans-serif;
        }
        h1, 
        h2{
            margin-left:10px;
        }
        .inner{
            display:inline-block;
            vertical-align:top;
            padding:5px;
            position:relative;
        }
        .inner img{
            width:100%;
        }
        .inner .outer-caption{
            color:black;
            width:375px;
            height:125px;
            background-color:#fc7cab;
            display:flex;
        }
        .inner .outer-caption .inner-caption{
            font-size:14px;
            font-family:sans-serif;
            overflow:hidden;
            width:320px;
            height:70px;
            margin:auto;
        }
        .inner .overlay-color{
            position: absolute;
            top:0;
            bottom:0;
            left:0;
            right:0;
            margin:auto;
            background-color: #fff;
            transition: all .5s;    
        }
        .inner .overlay-text{
            border: 2px solid #7e7e7e;
            color:#7e7e7e;
            font-size: 10px;
            position: absolute;
            top:0;
            bottom:0;
            left:0;
            right:0;
            width:70px;
            height:35px;
            line-height:35px;
            margin:auto;
            border-radius:1px;
            text-align: center;
            transition: all .5s;

    </style>

<body>  
    <h1>{{title}}</h1> 
    <h2>{{myMessage}}</h2>
    <div id="outer" class="outer">
        <div class="inner" ng-mouseenter="makeVisibile()" ng-mouseleave="makeInVisibile()" ng-repeat="x in insideData">
            <img ng-if="x.service=='Instagram'||(x.service=='Twitter' && x.mediaType=='image')" ng-src='{{x.thumbnails[0].url}}'>
             <div ng-if="x.service=='Twitter'&& x.mediaType!='image'" class="outer-caption"><div class="inner-caption">{{x.caption}}</div></div>
            <div class="overlay-color" ng-style="overlayColorStyles" ></div>
            <div class="overlay-text" ng-style="overlayTextStyles">VIEW</div>
        </div>
    </div>

<script>

    // Create the module
    var appModule = angular.module('appName', []);

    // Create rootScope variables
    appModule.run(
        function($rootScope){
            $rootScope.title = "Taneleer Demonstration";
        }
    );

    // Create the controller
    appModule.controller('appCtrl', function($scope, $http) {

        $scope.overlayColorStyles = {"opacity": 0};
        $scope.overlayTextStyles =  {"opacity": 0};

        $scope.makeVisibile = function(){
            //alert("test"); 
            //document.getElementById("overlay-color").style.opacity = .75;
            //document.getElementById("overlay-text").style.opacity = 1;
            $scope.overlayColorStyles = {"opacity" : .75};
            $scope.overlayTextStyles = {"opacity" : 1};

        }
        $scope.makeInVisibile = function(){
            //alert("test"); 
            //document.getElementById("overlay-color").style.opacity = 0;
            //document.getElementById("overlay-text").style.opacity = 0;
            $scope.overlayColorStyles = {"opacity" : 0};
            $scope.overlayTextStyles = {"opacity" : 0};

        }

        $http({
                method : "GET",
                url : "https://taneleer.composedcreative.com/api/v1/feed/a0329f16-9225-11e6-89bb-296a97b9d609/bb0429f6-f0ca-11e7-8f5d-d92739a9a53f"
            }).then(function mySucces(response) {

                $scope.myMessage = "Success!";

                $scope.response = response;
                $scope.meta = response.data.meta;
                $scope.outsideData = response.data;
                $scope.insideData = response.data.data;
                $scope.links = response.data.links;

                $scope.selfLink = response.data.links.self;
                $scope.firstLink = response.data.links.first;
                $scope.lastLink = response.data.links.last;
                $scope.nextLink = response.data.links.next;
                $scope.prevLink = response.data.links.prev;

                $scope.statuscode = response.status;
                $scope.statustext = response.statusText;
                $scope.statusheaders = response.headers(); 
                $scope.statusconfig = response.config;   

            }, function myError(response) {
                $scope.myMessage = "Error!";
                $scope.response = response;
                $scope.statuscode = response.status;
                $scope.statustext = response.statusText;
                $scope.statusheaders = response.headers(); 
                $scope.statusconfig = response.config;   
            });


        $scope.getNext = function() {
            $http({
                method : "GET",
                url : $scope.nextLink
            }).then(function mySucces(response) {

                $scope.myMessage = "Success!";
                $scope.response = response;
                $scope.outsideData = response.data;
                $scope.meta = response.data.meta;

                $scope.insideData = $scope.insideData.concat(response.data.data);

                $scope.links = response.data.links;
                $scope.selfLink = response.data.links.self;
                $scope.firstLink = response.data.links.first;
                $scope.lastLink = response.data.links.last;
                $scope.nextLink = response.data.links.next;
                $scope.prevLink = response.data.links.prev;

                $scope.statuscode = response.status;
                $scope.statustext = response.statusText;
                $scope.statusheaders = response.headers(); 
                $scope.statusconfig = response.config;   

            }, function myError(response) {
                $scope.myMessage = "Error!";
                $scope.response = response;
                $scope.statuscode = response.status;
                $scope.statustext = response.statusText;
                $scope.statusheaders = response.headers(); 
                $scope.statusconfig = response.config;   
            });
        }
        $(window).scroll(function() {
            if($(window).scrollTop() + $(window).height() == $(document).height()) {
                $scope.getNext();
            }
        });
    });

</script>

你好, 再次感谢亚伦的回答。我还有一个问题需要解决。我现在正在构建应用程序的灯箱部分。这就是您单击查看按钮时看到的叠加层。我把最新的版本放在网上: http://www.petermingione.com/my-demo/ 正如您所看到的,无论您单击哪个图像,唯一出现的图像是集合中的第一张图像。这又是 ng-repeat 的另一个问题。该图像作为 mainImage.url 位于每个对象中,我通过 ng-repeat 循环中的 x.mainImage.url 访问它。我不确定为什么它不起作用。任何人都可以给我的任何帮助将不胜感激。代码如下,在线:

   <style>
    * {
        box-sizing: border-box;
        font-family: sans-serif;
    }
    h1, 
    h2{
        margin-left:10px;
    }

    .outer-wrapper{
        overflow: hidden;
    }
    .inner-wrapper{
        display:inline-block;
        vertical-align:top;
        padding:5px;
        position:relative;
    }
    .inner-wrapper img{
        width:100%;
    }
    .inner-wrapper .outer-caption{
        color:black;
        width:100%;
        padding-top:35%;
        background-color:#fc7cab;
        position:relative;
    }
    .inner-wrapper .outer-caption .inner-caption{
        font-size:14px;
        font-family:sans-serif;
        overflow:hidden;
        width:75%;
        height:70px;
        position:absolute;
        top:0;
        left:0;
        bottom:0;
        right:0;
        margin:auto;
    }
    .inner-wrapper .item-overlay-color{
        position: absolute;
        top:0;
        bottom:0;
        left:0;
        right:0;
        margin:auto;
        background-color: #fff;
        transition: all .5s;
        opacity: 0.0;   
    }
    .inner-wrapper:hover .item-overlay-color {
        opacity: 0.75;
    }
    .inner-wrapper .item-overlay-text{
        border: 2px solid #7e7e7e;
        color:#7e7e7e;
        font-size: 10px;
        position: absolute;
        top:0;
        bottom:0;
        left:0;
        right:0;
        width:70px;
        height:35px;
        line-height:35px;
        margin:auto;
        border-radius:1px;
        text-align: center;
        transition: all .5s;
        opacity: 0.0;
    }
    .inner-wrapper:hover .item-overlay-text {
        opacity: 1.0;
    }
    .inner-wrapper .page-overlay {
        position: fixed;
        width: 100%;
        height: 100%;
        top: 0; 
        left: 0;
        right: 0;
        bottom: 0;
        background-color: rgba(255,255,255,0.75);
        z-index: 2;
        cursor: pointer;
    }
    .inner-wrapper #page-overlay {
        opacity:0;
        transition: all .5s;
        pointer-events:none;
    }
    .inner-wrapper .page-overlay .text{
        position: absolute;
        top: 50%;
        left: 50%;
        font-size: 50px;
        color: white;
        transform: translate(-50%,-50%);
        -ms-transform: translate(-50%,-50%);
    }
    .inner-wrapper .page-overlay .text .close{
        position:absolute;
        top:0;
        right:0;
        color:#000;
        font-weight: lighter;
        font-size: 30px;
        line-height: 30px;
        padding-top:5px;
        padding-right:5px;
    }

    @media screen and (min-width: 1301px){
        .inner-wrapper{
            width:16.6666%;
        }
    }
    @media screen and (max-width: 1300px){
        .inner-wrapper{
            width:20%;
        }
    }
    @media screen and (max-width: 1024px){
        .inner-wrapper{
            width:25%;
        }
    }
    @media screen and (max-width: 768px){
        .inner-wrapper{
            width:50%;
        }
    }
    @media screen and (max-width: 480px){
        .inner-wrapper{
            width:100%;
        }
    }

  </style>

 <body>
<div id="outer-wrapper" class="outer-wrapper">
    <div id="inner-wrapper" class="inner-wrapper" ng-repeat="x in insideData">
        <img ng-if="x.service=='Instagram'||(x.service=='Twitter' && x.mediaType=='image')" ng-src='{{x.thumbnails[0].url}}'>
        <div class="outer-caption" ng-if="x.service=='Twitter'&& x.mediaType!='image'">
            <div class="inner-caption">{{x.caption}}</div>
        </div>
        <div class="item-overlay-color"></div>
        <div class="item-overlay-text" ng-click="showOverlay()">VIEW</div>
        <div id="page-overlay" class="page-overlay">
                <div class="text">
                    <img ng-src='{{x.mainImage.url}}'>
                    <span class="close" ng-click="hideOverlay()">X</span>
                </div>
        </div>
    </div>
</div>
 </body>
  <script>
    // Create the module
    var appModule = angular.module('appName', []);

    // Create rootScope variables
    appModule.run(
        function($rootScope){
            $rootScope.title = "Taneleer Demonstration";
        }
    );

    // Create the controller
    appModule.controller('appCtrl', function($scope, $http) {

        $scope.showOverlay = function(){
            document.getElementById("page-overlay").style.opacity = 1;
            document.getElementById("page-overlay").style["pointer-events"] = "auto";
        }
        $scope.hideOverlay = function(){
            document.getElementById("page-overlay").style.opacity = 0;
            document.getElementById("page-overlay").style["pointer-events"] = "none";
        }

        $http({
                method : "GET",
                url : "https://taneleer.composedcreative.com/api/v1/feed/a0329f16-9225-11e6-89bb-296a97b9d609/bb0429f6-f0ca-11e7-8f5d-d92739a9a53f"
            }).then(function mySucces(response) {

                $scope.myMessage = "Success!";

                $scope.response = response;
                $scope.meta = response.data.meta;
                $scope.outsideData = response.data;
                $scope.insideData = response.data.data;
                $scope.links = response.data.links;

                $scope.selfLink = response.data.links.self;
                $scope.firstLink = response.data.links.first;
                $scope.lastLink = response.data.links.last;
                $scope.nextLink = response.data.links.next;
                $scope.prevLink = response.data.links.prev;

                $scope.statuscode = response.status;
                $scope.statustext = response.statusText;
                $scope.statusheaders = response.headers(); 
                $scope.statusconfig = response.config;   

            }, function myError(response) {
                $scope.myMessage = "Error!";
                $scope.response = response;
                $scope.statuscode = response.status;
                $scope.statustext = response.statusText;
                $scope.statusheaders = response.headers(); 
                $scope.statusconfig = response.config;   
            });


        $scope.getNext = function() {
            $http({
                method : "GET",
                url : $scope.nextLink
            }).then(function mySucces(response) {

                $scope.myMessage = "Success!";
                $scope.response = response;
                $scope.outsideData = response.data;
                $scope.meta = response.data.meta;

                $scope.insideData = $scope.insideData.concat(response.data.data);

                $scope.links = response.data.links;
                $scope.selfLink = response.data.links.self;
                $scope.firstLink = response.data.links.first;
                $scope.lastLink = response.data.links.last;
                $scope.nextLink = response.data.links.next;
                $scope.prevLink = response.data.links.prev;

                $scope.statuscode = response.status;
                $scope.statustext = response.statusText;
                $scope.statusheaders = response.headers(); 
                $scope.statusconfig = response.config;   

            }, function myError(response) {
                $scope.myMessage = "Error!";
                $scope.response = response;
                $scope.statuscode = response.status;
                $scope.statustext = response.statusText;
                $scope.statusheaders = response.headers(); 
                $scope.statusconfig = response.config;   
            });
        }
        $(window).scroll(function() {
            if($(window).scrollTop() + $(window).height() == $(document).height()) {
                $scope.getNext();
            }
        });
    });

最佳答案

我知道您问过如何以 Angular 方式执行此操作,但是 ng-mouseenter 和 ng-mouseleave 是非常耗费性能的,如果您打算在真实世界的应用程序中使用它,那么这真的应该使用 css 来完成。

我会继续向您展示如何修复您的版本,然后我会给您一个更高效的 css 版本:)

对于这个用例,有一个非常有用的变量 $index,它可以在 ng-repeat 标签内的任何地方的 Angular 模板中引用,以获取当前数据项的索引迭代了。您应该使用它来保存当前悬停在 Controller 范围内的元素的索引。然后,当鼠标离开该元素时,您可以丢弃保存的索引。

然后,当您分配样式时,您可以使用三元组根据元素索引是否与保存在范围内的事件索引变量匹配来分配事件或非事件样式。

此外,如果您不熟悉,三元表达式是 conditional_expression 形式的条件语句的简写? value_returned_if_true :value_returned_if_false。它非常适合用 javascript 编写非常简洁的条件语句(或者,在这种情况下,一个带有解释 javascript 的 Angular 模板:))

因此,对于这个例子,我使用三元表达式的组合并保存鼠标输入的最后一个元素的索引来为每个元素分配悬停或非悬停样式。

以及您示例的缩写版本:

Angular Controller :

app.controller('exampleController', function($scope) {
  $scope.overlayColorStyles = {"opacity": 0};
  $scope.overlayTextStyles  = {"opacity": 0};
  $scope.overlayTextStylesActive  = {"opacity": 1};
  $scope.overlayColorStylesActive = { "opacity": .75};
  $scope.activeItemIndex    = null;
});

模板:

<div id="outer" class="outer">
  <div class="inner"
      ng-mouseenter="$scope.activeItemIndex = $index"
      ng-mouseleave="$scope.activeItemIndex = null"
      ng-repeat="x in insideData">
      <img ng-if="x.service=='Instagram'||(x.service=='Twitter' && x.mediaType=='image')" ng-src='{{x.thumbnails[0].url}}'>
      <div ng-if="x.service=='Twitter'&& x.mediaType!='image'" class="outer-caption"><div class="inner-caption">{{x.caption}}</div></div>
      <div class="overlay-color"
        ng-style="$scope.activeItemIndex === $index ? overlayColorStylesActive : overlayColorStyles">
      </div>
      <div class="overlay-text"
        ng-style="$scope.activeItemIndex === $index ? overlayTextStylesActive : overlayTextStyles">
        VIEW
      </div>
  </div>
</div>

不过,此代码只能用于学习练习。 Angular 的工作不是根据用户交互应用样式,如果您尝试以这种方式使用它,当您开始添加更多元素时,您的应用程序会变得非常慢。使用 css 执行此操作非常简单,并且会显着提高性能 :)

css 版本如下:

html:

<div id="outer" class="outer">
  <div class="inner"
      ng-repeat="x in insideData">
      <img ng-if="x.service=='Instagram'||(x.service=='Twitter' && x.mediaType=='image')" ng-src='{{x.thumbnails[0].url}}'>
      <div ng-if="x.service=='Twitter'&& x.mediaType!='image'" class="outer-caption"><div class="inner-caption">{{x.caption}}</div></div>
      <div class="overlay-color"></div>
      <div class="overlay-text">VIEW</div>
  </div>
</div>

CSS

.overlay-color {
  opacity: 0.0;
}

.overlay-text {
  opacity: 0.0;
}

.inner:hover .overlay-text {
  opacity: 1.0;
}

.inner:hover .overlay-color {
  opacity: 0.75;
}

关于javascript - 如何在 ng-repeat 循环中分配一个 angularjs 事件监听器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50183582/

相关文章:

javascript - 使用 Chrome 进行 WebStorm 调试 - 具有有用控制台和在 WebStorm 中设置断点的最佳工作流程

javascript - 为什么这个正则表达式/DOM字符实体测试器返回 `undefined`?

html - 在 Wordpress 中设置 HTML 按钮的样式

javascript - 窗口弹出窗口 - 如何让 window.blur() 或 window.focus() 在 FireFox 4 中工作?

css - 如何在 Susy 中获取 "stacking grid"(在另一列之上)

jquery - 遍历子 <li> 并删除类?

javascript - HTML5 详细信息-> 摘要

javascript - 何时以及为何使用这些不同的 Javascript 函数声明格式?

javascript - 对 JSON 和 Javascript 的安全性感到非常困惑(和担心)

html - 在 css 文件中为其指定固定位置后的导航栏奇怪行为