Open msforest opened 7 years ago
之前对js版的通讯录进行了一些修改,数据从静态改成动态加载显示,经过一番思考后很快就改完了。现在要将通讯录在angular中使用,考虑到数据也是动态加载,有点小麻烦。一一记录在此: 按照angular的思想,操作DOM结构不应该写在controller里,应该用指令来进行封装,而复杂业务逻辑应该写服务中。 尝试用angular写的代码如下: 一个精简的页面ng-txl.html
<!DOCTYPE html> <html ng-app='app'> <head> <meta charset="utf-8"> <title>ng-txl</title> <link rel="stylesheet" href="style.css"> <script type="text/javascript" src="jquery-1.8.3.min.js"></script> <script type="text/javascript" src="angular.js"></script> <script type="text/javascript" src="jquery.charfirst.pinyin.js"></script> <script type="text/javascript" src="ng-txl.js"></script> </head> <body> <div ng-controller="txlCtrl"> <txl></txl> </div> </body> </html>
然后是ng-txl.js,我将service,directive,controller写在一起了,当然,这是不可取的。
var app = angular.module('app',[]); app.service('InitialSort', function(){ this.sort = function(html){ var Initials=$('.initials'); var LetterBox=$('#letter'); Initials.find('ul').append('<li>A</li><li>B</li><li>C</li><li>D</li><li>E</li><li>F</li><li>G</li><li>H</li><li>I</li><li>J</li><li>K</li><li>L</li><li>M</li><li>N</li><li>O</li><li>P</li><li>Q</li><li>R</li><li>S</li><li>T</li><li>U</li><li>V</li><li>W</li><li>X</li><li>Y</li><li>Z</li><li>#</li>'); initials2(html); $(".initials ul li").click(function(){ var _this=$(this); var LetterHtml=_this.html(); LetterBox.html(LetterHtml).fadeIn(); Initials.css('background','rgba(145,145,145,0.6)'); setTimeout(function(){ Initials.css('background','rgba(145,145,145,0)'); LetterBox.fadeOut(); },1000); var _index = _this.index() if(_index==0){ $('html,body').animate({scrollTop: '0px'}, 300);//点击第一个滚到顶部 }else if(_index==27){ var DefaultTop=$('#default').position().top; $('html,body').animate({scrollTop: DefaultTop+'px'}, 300);//点击最后一个滚到#号 }else{ var letter = _this.text(); if($('#'+letter).length>0){ var LetterTop = $('#'+letter).position().top; $('html,body').animate({scrollTop: LetterTop-45+'px'}, 300); } } }) var windowHeight=$(window).height(); var InitHeight=windowHeight-45; Initials.height(InitHeight); var LiHeight=InitHeight/28; Initials.find('li').height(LiHeight); } }); app.directive('initialSort', ['$compile', 'InitialSort', function($compile, InitialSort){ return { restrict:'EC', template: `<div> <div id="letter" ></div> <div class="sort_box"></div> <div class="initials"> <ul> <li><img src="img/068.png"></li> </ul> </div> </div>`, link:function(scope, element, attr){ var html = [], item=null; for(var i = 0,len = scope.chineseArr.length; i < len; i++){ item = chineseArr[i]; html += `<div class="sort_list" ng-click=payee(${JSON.stringify(item)})><div class="num_name">${item.name}</div></div>`; item = null; } InitialSort.sort(html); $compile(element.contents())(scope); //使用compile对dom进行再次编译 } } }]); app.controller('txlCtrl', ['$scope', function($scope){ $scope.chineseArr = [ {"id":1,name:"涨水"}, {"id":2,name:"美女"}, {"id":3,name:"准备"}, {"id":4,name:"请问"}, {"id":5,name:"水电费"}, {"id":6,name:"不能"}, {"id":7,name:"更好"}, {"id":8,name:"熬吧"}, {"id":9,name:"凉快了"}, {"id":10,name:"潍坊"}, {"id":11,name:"拉屎"}, {"id":12,name:"胸围"}, {"id":13,name:"漂亮"}, {"id":14,name:"离开"}, {"id":15,name:"额无法"}, {"id":16,name:"123"}, {"id":17,name:"+sdkl"}, {"id":18,name:"AB"} ]; $scope.payee = function(item){ console.log(item); } }]);
这里有用到es6的模板字符串,想想它比字符串拼接更简单,我就用了,因为正好我开始看es6方面的知识了。 以上代码是没有问题的,效果也是OK的,现在说说在编写directive的过程中遇到的问题:
一开始按照基本的指令编写方式完成,页面展示的效果也是没问题的,beautiful.但是click没有用,控制台没有打印我想要的东西,其实知道问题出现在哪儿,指令template的模板,然后在link函数对template进行动态修改dom结构,这时,使用的ng-click肯定是没有效果的,这需要对angular的指令生命周期要有一点了解,不然问题出现在哪儿都不知道,在link函数里动态添加的dom结构不在angular监听范围内,这个时候的dom结构几乎已经出现在真实页面中展示了,要想对link函数动态添加的dom结构使用ng的东西,需要对动态dom进行angular的强制编译,来达到在我的监管范围内的目的,即使用$compile。这时,ng-click就有效了, 到这一步的时候,控制台还有一点错误,和往常一样的写法ng-click=payee(item),这不会报错,但是item具体的对象值没有传递过来,而是传了'item'字符串,这我又不乐意了,于是,改成了ng-click=payee(${item}),控制台报错,这就好办了,有错误就代表有解决方案,没错误才是最危险的,报什么传递的是对象[object,object],不符合语法规范,然后在stackoverflow网上找到解决方案,就是上面所写的ng-click=payee(${JSON.stringify(item)}),这样问题就没了。
ng-click=payee(item)
item
'item'
ng-click=payee(${item})
ng-click=payee(${JSON.stringify(item)})
2016.11.30 今天又发现了一个问题,就是通讯录显示的数据不会随着数据的更新而更新,这算是一个很严重的问题,所幸发现的早,有更多的时间去解决,这里发解决方案记录一下: 指令的生成是根据chineseArr值来变化的,所以我们去监听chineseArr值的变化
link:function(scope, element, attr){ //对新旧值进行监听保证数据变化时,指令也要更新 scope.$watch('chineseArr',function(newValue,oldValue){ if (newValue){ $(element).find('.sort_box').html(""); //置空原有html var html = [], item=null; for(var i = 0,len = scope.chineseArr.length; i < len; i++){ item = scope.chineseArr[i]; html += `<div class="sort_list" ng-click=payee(${JSON.stringify(item)})><div class="num_name">${item.name}</div></div>`; item = null; } InitialSort.sort(html, scope.chineseArr); $compile(element.contents())(scope); //使用compile对dom进行再次编译 } }); }
一开始我一直在想怎么让指令重新渲染,问过一些人,也搜了网上,都是说用$compile重新编译,这种方法没用,郁闷了一小会。
2016-12-25 增加触摸字母列表滑动的功能,修改自定义服务
app.service('InitialSort', function(){ this.sort = function(html, list){ var Initials=$('.initials'); var LetterBox=$('#letter'); Initials.find('ul').append('<li>A</li><li>B</li><li>C</li><li>D</li><li>E</li><li>F</li><li>G</li><li>H</li><li>I</li><li>J</li><li>K</li><li>L</li><li>M</li><li>N</li><li>O</li><li>P</li><li>Q</li><li>R</li><li>S</li><li>T</li><li>U</li><li>V</li><li>W</li><li>X</li><li>Y</li><li>Z</li><li>#</li>'); initials2(html, list); $(".initials ul li").on('click', function(e){ var _this=$(this); var LetterHtml=_this.html(); LetterBox.html(LetterHtml).fadeIn(); Initials.css('background','rgba(145,145,145,0.6)'); setTimeout(function(){ Initials.css('background','rgba(145,145,145,0)'); LetterBox.fadeOut(); },1000); var _index = _this.index() if(_index==0){ $('html,body').animate({scrollTop: '0px'}, 300);//点击第一个滚到顶部 }else if(_index==27){ var DefaultTop=$('#default').position().top; $('html,body').animate({scrollTop: DefaultTop+'px'}, 300);//点击最后一个滚到#号 }else{ var letter = _this.text(); if($('#'+letter).length>0){ var LetterTop = $('#'+letter).position().top; $('html,body').animate({scrollTop: LetterTop-45+'px'}, 300); } } }); $('.initials ul').on('touchmove', function(event){ event.preventDefault(); var x = event.originalEvent.targetTouches[0].clientX; var y = event.originalEvent.targetTouches[0].clientY; var target = document.elementFromPoint(x,y); if(!target) return ; var LetterHtml=target.innerHTML, arr = '<img src="images/star.png">abcdefghijklmnopqrstuvwxyz#'; if(arr.indexOf(LetterHtml.toLowerCase()) === -1) return ; console.log(LetterHtml) LetterBox.html(LetterHtml).fadeIn(); if('<img src="img/068.png">' === LetterHtml){ $('html,body').animate({scrollTop: '0px'}, 0);//点击第一个滚到顶部 }else if('#' === LetterHtml){ var DefaultTop=$('#default').position().top; $('html,body').animate({scrollTop: DefaultTop+'px'}, 0);//点击最后一个滚到#号 }else{ var letter = LetterHtml; if($('#'+letter).length>0){ var LetterTop = $('#'+letter).position().top; $('html,body').animate({scrollTop: LetterTop-45+'px'}, 0); } } }).on('touchstart', function(e){ Initials.css('background','rgba(145,145,145,0.6)'); }).on('touchend', function(e){ setTimeout(function(){ Initials.css('background','rgba(145,145,145,0)'); LetterBox.fadeOut(); },500); }); var windowHeight=$(window).height(); var InitHeight=windowHeight-45; Initials.height(InitHeight); var LiHeight=InitHeight/28; Initials.find('li').height(LiHeight); } });
代码在文件夹的ng命名的文件
It is not easy to meet each other in such a big world.- -世界这么大,能遇见,不容易。
过滤repeat的结果指令用法:
<div ng-repeat="person in persons | filter:name as results"> {{person.name}} </div> <li ng-show="results.length == 0"> <strong>No results found...</strong> </li>
之前对js版的通讯录进行了一些修改,数据从静态改成动态加载显示,经过一番思考后很快就改完了。现在要将通讯录在angular中使用,考虑到数据也是动态加载,有点小麻烦。一一记录在此: 按照angular的思想,操作DOM结构不应该写在controller里,应该用指令来进行封装,而复杂业务逻辑应该写服务中。 尝试用angular写的代码如下: 一个精简的页面ng-txl.html
然后是ng-txl.js,我将service,directive,controller写在一起了,当然,这是不可取的。
这里有用到es6的模板字符串,想想它比字符串拼接更简单,我就用了,因为正好我开始看es6方面的知识了。 以上代码是没有问题的,效果也是OK的,现在说说在编写directive的过程中遇到的问题:
一开始按照基本的指令编写方式完成,页面展示的效果也是没问题的,beautiful.但是click没有用,控制台没有打印我想要的东西,其实知道问题出现在哪儿,指令template的模板,然后在link函数对template进行动态修改dom结构,这时,使用的ng-click肯定是没有效果的,这需要对angular的指令生命周期要有一点了解,不然问题出现在哪儿都不知道,在link函数里动态添加的dom结构不在angular监听范围内,这个时候的dom结构几乎已经出现在真实页面中展示了,要想对link函数动态添加的dom结构使用ng的东西,需要对动态dom进行angular的强制编译,来达到在我的监管范围内的目的,即使用$compile。这时,ng-click就有效了, 到这一步的时候,控制台还有一点错误,和往常一样的写法
ng-click=payee(item)
,这不会报错,但是item
具体的对象值没有传递过来,而是传了'item'
字符串,这我又不乐意了,于是,改成了ng-click=payee(${item})
,控制台报错,这就好办了,有错误就代表有解决方案,没错误才是最危险的,报什么传递的是对象[object,object],不符合语法规范,然后在stackoverflow网上找到解决方案,就是上面所写的ng-click=payee(${JSON.stringify(item)})
,这样问题就没了。2016.11.30 今天又发现了一个问题,就是通讯录显示的数据不会随着数据的更新而更新,这算是一个很严重的问题,所幸发现的早,有更多的时间去解决,这里发解决方案记录一下: 指令的生成是根据chineseArr值来变化的,所以我们去监听chineseArr值的变化
一开始我一直在想怎么让指令重新渲染,问过一些人,也搜了网上,都是说用$compile重新编译,这种方法没用,郁闷了一小会。
2016-12-25 增加触摸字母列表滑动的功能,修改自定义服务
代码在文件夹的ng命名的文件