基于AngularJs的联想搜索框组件封装

组件组成:HTML模板 + JS文件

组件原理:HTML模板就是规定组件由哪些元素构成,这些元素是什么结构的,既组件是长啥样的;JS文件是用来声明和定义组件功能的,相当于JSP文件中<script>标签中JS代码的功能;

联想搜索:用户在输入框中输入关键字,并自动向后端发送异步请求,得到请求回来的数据后,以列表的形式展示在搜索框下方,用户通过鼠标悬停或者上下键选择选项,鼠标点击或者Enter键实现搜索并列表消失的功能,功能如下图:

代码部分

  • HTML模板:
1 <span class="relative">
2     <input type="text" placeholder="请输入关键字..." ng-model="inputModel" ng-change="method.timeflash()" ng-blur="method.closeSearch()" ng-focus="method.searchData()" ng-keydown="method.keyDownEvent($event)">
3     <i class="iconfont searchBtn"></i>
4     <span class="search-list" ng-show="vm.dataList.length > 0" id="forhide">
5         <a href="javascript:void(0)" ng-repeat="data in vm.dataList | limitTo:10"
6            ng-mouseover="method.mouseOverEvent($index)" ng-click="method.enterKeyEvent(data)">{{data.value}}</a>
7     </span>
8 </span>

注解:输入框对象$scope.inputModel用于保存输入的关键字,输入框提供change、blur、focus、keydown事件的监听。

  change事件:当输入框内容变化时,触发计时器,400毫秒后开始搜索;

  blur事件:搜索框失焦时,清空并隐藏数据列表;

  focus事件:输入框获得焦点时,直接搜索;

  keydown事件:按键监听事件,监听上下键及Enter事件,上下键选择列表中的数据项,Enter键做用户指定操作。

  • CSS类:
 1 .relative{position: relative!important;}
 2 .absolute{position: absolute!important;}
 3 
 4 .search-list {
 5     position: relative;
 6     width: 100%;
 9     background: #fff;
10     border: solid 1px #5093e1;
11     z-index: 10;
12 }
13 
14 .search-list a {
15     width: 100%;
16     height: 30px;
17     line-height: 30px;
18     float: left;
19     color: #666;
20     display: block;
21     font-size: 13px;
22     padding: 0 10px;
23     text-decoration: none;
24 }
25 
26 .search-list a:hover {
27     color: #666;
28 }
29 
30 .search-list .selected {
31     background: #5093e1;
32     color: #fff!important;
33 }

注解:数据列表相对于搜索框相对布局。

  • JS文件
  1 APP.directive('search', ['Postman','$timeout', function (Postman,$timeout) {
  2     return {
  3         scope: {// 传入的参数
  4             inputModel: '=',// 输入框对象
  5             enterKeyEvent: '='// 用户指定操作
  6         },
  7         restrict: 'E',// 封装成Element(元素)类型
  8         templateUrl: 'directive/search/search.html',// 模板路径
  9         replace: false,
 10         link: function ($scope) {
 11             var timer;
 12             var selectListIndex;// 数据列表索引
 13             $scope.vm = {};// 模板视图对象
 14             $scope.method = {};// 模板方法对象
 15 
 16             function initParams(){// 初始化参数
 17                 $scope.vm = {
 18                     selectedData: {},// 选中数据对线
 19                     dataList: []// 数据列表
 20                 };
 21                 $scope.method.enterKeyEvent = $scope.enterKeyEvent;//将传过来的用户指定的方法赋值给组件
 22             }
 23 
 24             function init() {// 程序初始化执行部分
 25                 initParams();
 26             }
 27 
 28             $scope.method.searchData = function () { // 根据关键字搜索联想词
 29                 if ($scope.inputModel === undefined) {// 为空时不做搜索
 30                     return;
 31                 }
 32                 if ($scope.inputModel.length > 0) {// 非空时异步请求联想词
 33                     var promise = Postman.httpGet('data/fuzzy', {// Postman为自己封装的Http请求服务,这里用Get方法请求数据
 34                         keyWord: $scope.inputModel});
 37                     promise.then(function (data) {
 38                         if (data && data.code === 0) {
 39                             $scope.vm.dataList = data.data;// 请求回来的数据赋值给视图对象中的dataList数组
 40                             selectListIndex = -1;// 索引置为-1,不选中任何项
 41                             $('#forhide').show();// 显示列表
 42                         }
 43                     });
 44                 }
 45             };
 46 
 47             $scope.method.keyDownEvent = function ($event) {
 48                 $event.stopPropagation();// 阻止其他按键事件冒泡
 49                 var listArry = $('#forhide>a');
 50                 switch ($event.keyCode) {
 51                     case 38:// 'UP'
 52                         selectListIndex--;
 53                         if (selectListIndex >= 0 && selectListIndex < listArry.length) {
 54                             for (var i = 0; i < listArry.length; i++) {
 55                                 listArry.eq(i).removeClass('selected');// 清除选中样式
 56                                 if (i === selectListIndex) {
 57                                     listArry.eq(i).addClass('selected');// 添加选中样式
 58                                     $scope.inputModel = listArry.eq(i).text();// 将选中项的文本赋值给输入框
 59                                 }
 60                             }
 61                         } else if (selectListIndex < 0) {// 第0项跳转到最后一项
 62                             selectListIndex = listArry.length - 1;
 63                             listArry.eq(0).removeClass('selected');
 64                             listArry.eq(selectListIndex).addClass('selected');
 65                             $scope.inputModel = listArry.eq(selectListIndex).text();
 66                         }
 67                         break;
 68                     case 40:// 'Down'
 69                         selectListIndex++;
 70                         if (selectListIndex >= 0 && selectListIndex < listArry.length) {
 71                             for (var i = 0; i < listArry.length; i++) {
 72                                 listArry.eq(i).removeClass('selected');
 73                                 if (i === selectListIndex) {
 74                                     listArry.eq(i).addClass('selected');
 75                                     $scope.inputModel = listArry.eq(i).text();
 76                                 }
 77                             }
 78                         } else if (selectListIndex >= listArry.length) {// 最后一项跳转到第0项
 79                             selectListIndex = 0;
 80                             listArry.eq(listArry.length - 1).removeClass('selected');
 81                             listArry.eq(selectListIndex).addClass('selected');
 82                             $scope.inputModel = listArry.eq(selectListIndex).text();
 83                         }
 84                         break;
 85                     case 13:// Enter键触发用户指定操作
 86                         $scope.method.enterKeyEvent($scope.vm.dataList[selectListIndex]);
 87                         $scope.method.closeSearch();// 关闭联想词列表
 88                         break;
 89                 }
 90             };
 91 
 92             $scope.method.mouseOverEvent = function (index) {// 鼠标悬停事件:获取悬停数据项的索引,并添加选中样式
 93                 selectListIndex = index;
 94                 var listArry = $('#forhide>a');
 95                 for (var i = 0; i < listArry.length; i++) {
 96                     listArry.eq(i).removeClass('selected');
 97                     if (i === selectListIndex) {
 98                         listArry.eq(i).addClass('selected');
 99                         $scope.inputModel = listArry.eq(i).text();
100                     }
101                 }
102             };
103 
104             $scope.method.timeflash = function () {// 定时器控制,400ms后才发送请求
105                 $timeout.cancel(timer);// 关闭400ms内的上一个计时器,400ms后认为用户停止输入,即输入完成,开始搜索,从而减少多余的请求次数
106                 timer = $timeout(function () {
107                     $scope.method.searchData();// 发送搜索请求
108                 }, 400);
109             };
110 
111             $scope.method.closeSearch = function () {// 关闭联想词列表
112                 $scope.vm.dataList = [];
113                 $('#forhide').hide();
114             };
115 
116             init();// 程序入口
122 } 123 }; 124 }]);
  • 使用样例:
1 <search input-model="inputBox" enter-key-event="search"></search>

传递组件需要的两个参数:inputModel和enterKeyEvent。"search"为用户指定的操作、方法。

转载于:https://www.cnblogs.com/hjx-blog/p/6597681.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值