场景:在开发聊天消息界面的项目中,一个非常常见的场景就是在聊天窗口中发送和接收信息时,需要将聊天记录窗口滑动条实时滑至底部。本人参考git上面的一个插件(参考地址:https://github.com/Luegg/angularjs-scroll-glue),自己摸索着开发了一个指令。在使用该插件之后,本人感觉有不爽的地方,只要点击界面任何位置,它都会滑至底部。相对于scroll-glue插件,我简化了该插件的实现,只保留滑动至底部的功能,同时可以动态设置是否生效该插件。
完整的angularJS的指令实现如下:
'use strict'; angular.module('myApp') .directive('scrollToBottom', ['$parse', '$window', '$timeout', function ($parse, $window, $timeout) { function createActivationState($parse, attr, scope) { function unboundState(initValue) { var activated = initValue; return { getValue: function () { return activated; }, setValue: function (value) { activated = value; } }; } function oneWayBindingState(getter, scope) { return { getValue: function () { return getter(scope); }, setValue: function () { } }; } function twoWayBindingState(getter, setter, scope) { return { getValue: function () { return getter(scope); }, setValue: function (value) { if (value !== getter(scope)) { scope.$apply(function () { setter(scope, value); }); } } }; } if (attr !== '') { var getter = $parse(attr); if (getter.assign !== undefined) { return twoWayBindingState(getter, getter.assign, scope); } else { return oneWayBindingState(getter, scope); } } else { return unboundState(true); } } return { priority: 1, restrict: 'A', link: function (scope, $el, attrs) { var el = $el[0], activationState = createActivationState($parse, attrs.scrollToBottom, scope); var bottom = { isAttached: function (el,isAttached) { return isAttached; }, scroll: function (el) { el.scrollTop = el.scrollHeight; } }; function scrollIfGlued() { if (activationState.getValue() && !bottom.isAttached(el, scope.isAttached)) { bottom.scroll(el); } } scope.$watch(scrollIfGlued); $timeout(scrollIfGlued, 0, false); $window.addEventListener('resize', scrollIfGlued, false); $el.bind('scroll', function () { activationState.setValue(bottom.isAttached(el,scope.isAttached)); }); } }; }]);
1、在聊天窗口所在元素中配置指令
2、控制当前controller的作用域scope.isAttached的值,该值控制指令的生效和失效,当scope.isAttached === false时,指令生效;否则失效。
代码示例:
(1)静态页面代码
scroll-to-bottom="true" ng-mouseenter="unbindGlued()" id="chatWindow">
ng-repeat="item in conversationlist">
message-info="item" value="{{item}}">
/** * 当点击聊天记录窗口时,不让滚动条自动滚至底部 * @type {boolean} */ //标示滚动条是否滑至底部 $scope.isAttached = false; $scope.unbindGlued = function(){ $scope.isAttached = true; }; /** * 聊天记录窗口失去焦点时,让滚动条自动滚至底部 * @type {boolean} */ $scope.bindGlued = function(){ $scope.isAttached = false; };在具体的聊天场景中,可以动态设置$scope.isAttached的值来控制滚动条滑至底部,比如接收和发送消息的时候,将$scope.isAttached 设为false,让指令生效;而当鼠标放在聊天窗口的时候,则将$scope.isAttached 设为false,如代码所示,此时可以防止当我们点击界面任何区域时,滚动条滑至底部。
欢迎大家有更好的方法提出来,大家一起交流!