疑似angularJs父子作用域,实际上却不是的一个小坑

本文介绍了一个基于AngularJS的自定义分页控件遇到的问题及解决过程。作者最初发现点击事件未能触发对应的link函数,经过排查最终定位到模板中的ng-if导致作用域丢失的问题,并给出了解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

这几天做了一个分页控件,使用angularJS进行编写,无奈发现,我的指令中的模板所触发的点击事件不会去link函数中找相对应的方法进行调用,而是去他的父作用域进行查找,自然是找不到相关的代码的,这就导致了点击控件没有反应的情况发生。
我的控件代码如下:

define(['angular','app','bootstrap'], function (angular,app) {
    app.directive('pageDirective', ['$rootScope',function ($rootScope) {
        return {
            restrict: 'E',
            templateUrl: 'app/external_library/page_directive/pagination.html',
            replace: true,
            scope: {
                conf: '='
            },
            link: function (scope, element, attrs) {
                scope.page = {};
                scope.init = function () {
                    console.log("初始化分页控件");
                    // 初始化一页展示多少条  默认为10
                    scope.conf.pageLimit = [10, 15, 20, 30, 50];
                    if (!scope.conf.itemPageLimit) {
                        scope.conf.itemPageLimit = scope.conf.pageLimit[0];
                    } else {
                        // 把自定义的条目加入到pagelimit中
                        if (scope.conf.pageLimit.indexOf(scope.conf.itemPageLimit)) {
                            scope.conf.pageLimit.push(scope.conf.itemPageLimit);
                            scope.conf.pageLimit = scope.conf.pageLimit.sort(function (a, b) {
                                return a - b;
                            });
                        }
                    }
                    //一共多少页
                    scope.page.limit = Math.floor(scope.conf.total / scope.conf.itemPageLimit);
                }
                // 上一页
                scope.prevPage = function () {
                    console.log("上一页");
                    if (scope.conf.currentPage <= 1) return;
                    scope.conf.currentPage -= 1;
                }
                // 下一页
                scope.nextPage = function () {
                    console.log("下一页");
                    if (scope.conf.currentPage >= scope.page.limit) return;
                    scope.conf.currentPage += 1;
                }
                // 改变一页显示条目
                scope.selectPage = function () {
                    console.log("改变一页显示条数");
                    scope.conf.currentPage = 1;
                    scope.page.limit = Math.floor(scope.conf.total / scope.conf.itemPageLimit);
                }
                // 跳转页
                scope.linkPage = function () {
                    console.log("跳转页");
                }
                scope.$watch("conf.total", function (newVal) {
                    if (angular.isUndefined(newVal)) {
                        scope.conf.total = 0;
                        scope.conf.currentPage = 1;
                    } else {
                        scope.init();
                    }
                });
            }
        }
    }]);
});

模板代码如下:

<div>
    <ul style="white-space:nowrap">
        <li ng-disable="conf.currentPage == 1" ng-click="prevPage()" style="display:inline-block;">
            <button href="#"><</button>
        </li>
        <li style="display:inline-block;">
            <div>
                <div><input style="width: 50px;" type="text" ng-model="conf.currentPage" ng-change="linkPage()"></div>
            </div>
        </li>
        <li ng-disable="conf.currentPage == page.limit" ng-click="nextPage($event)" style="display:inline-block;">
            <button href="#">></button>
        </li>
        <li style="display:inline-block;">
            <div>
                <div>
                    一页<select ng-options="limit for limit in conf.pageLimit" ng-model="conf.itemPageLimit"
                              ng-change="selectPage()"></select></div>
            </div>
        </li>
        <li style="display:inline-block;">
            <div><span>{{page.limit}}</span></div>
        </li>
    </ul>
</div>

仔仔细细检查多遍,并没有发现什么有可能导致以上问题的错误。于是我怀疑是作用域的问题,在查找了一些资料后,发现并不是这个问题,因为分页控件的特殊性,他需要一个新的作用域,并且又要将当前页传递出去,做好的做法应该就是这样了:

return {
            restrict: 'E',
            templateUrl: 'app/external_library/page_directive/pagination.html',
            replace: true,
            scope: {
                conf: '='
            }...
            }

在无奈之下,只有妥协,既然他只能找到controller中的方法,那我就给他一个。于是在指令中使用了指定的controller。但是依旧不行。在这个过程中,我发现它能够进行初始化的操作。也就是说,相关数据其实是可以传递进来的,那么代码就是没有问题的。
换个思维,既然代码没有问题,那就只能是模板的问题了。我将模板全部删除,只保留了一个最简单的button按钮,绑定了一个最简单的click事件,打印了一串字符串。一次通过。
这个时候问题就被定位了——就是模板的问题。又细细研读了自己的模板一次,发现原来是ng-if惹的祸。修改后的代码如下所示:

<div>
    <ul style="white-space:nowrap">
        <li ng-disable="conf.currentPage == 1" ng-click="prevPage()" style="display:inline-block;">
            <button href="#"><</button>
        </li>
        <li style="display:inline-block;">
            <div>
                <div><input style="width: 50px;" type="text" ng-model="conf.currentPage" ng-change="linkPage()"></div>
            </div>
        </li>
        <li ng-disable="conf.currentPage == page.limit" ng-click="nextPage($event)" style="display:inline-block;">
            <button href="#">></button>
        </li>
        <li style="display:inline-block;">
            <div>
                <div>
                    一页<select ng-options="limit for limit in conf.pageLimit" ng-model="conf.itemPageLimit"
                              ng-change="selectPage()"></select></div>
            </div>
        </li>
        <li style="display:inline-block;">
            <div><span>{{page.limit}}</span></div>
        </li>
    </ul>
</div>

就只差了开头的一点点,如果在第一次加载指令进行编译的时候,ng-if会将相关的DOM移除,第二次初始化的时候自然也就没有了相关的作用域,angular就会向上搜索父作用域。从而 导致了现在的问题。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值