用angular写多选组件以及开发时的所思所想

这里是demo

我是一个angular1系列的重度爱好者,为什么喜欢它呢,因为我觉得angular1是接口设计的最漂亮的框架,虽然现在vue确实很火,但是我觉得vue的Expression部分并不足够智能。另外,可能是我的思维定势,我还是觉得Expression应该和一个对象互相绑定,就像我写的前端框架那样。怎么说呢,我坚持使用angular1,也许也是因为它的设计思路和我的思路更符合吧。当然,争论前端框架的优劣是很没意思的,所以其实在有的项目中,我也是选择了vue,没有什么原因,只是随心所欲而已。

其实用angular1写组件(也就是指令)是几乎每个使用者都会的,不过这次我的所思所想并不只是如何写代码而已,这经历了三个过程:

  1. 多选框的最好形式是什么?真的是前面画对勾选中吗?
  2. 一个组件如何设计的优雅,让前端傻瓜都会用?
  3. 我的以上想法是不是多余的?

1.多选框的最好形式是什么?真的是前面画对勾选中吗?

其实对勾的多选框并不是一个很好的形式,因为它样式很烦人,前面一个input标签后面一个span或者label标签,看起来就很乱;垂直居中也不好调,动不动就出问题;每一个checkbox都要绑定一个ngModel,有时候就会觉得头很懵,因为有太多ngModel;如果checkbox很多的话,排版也很乱:

用angular写多选组件以及开发时的所思所想_第1张图片
这真的是多选吗?

所以我觉得应该换一种思路去多选,我觉得标签这种东西其实更适合多选。

2. 组件应该如何设计

我个人觉得,组件的设计应该非常符合正常人的思路:
既然是数据处理,那么组件作为一个黑盒,只需要让用户输入一个值,然后得到一个值就行。又既然是多选,那么让用户输入一个数组,然后得到一个新的数组就可以了。下面是一个数组:

$scope.userList=[
        {
            name:'樱木花道',
            height:189.5
        },
        {
            name:'流川枫',
            height:187
        },
        {
            name:'三井寿',
            height:183
        },
        {
            name:'宫城良田',
            height:168
        },
        {
            name:'赤木刚宪',
            height:197
        },
    ]

在组件中将上面的数组作为输入值:是组件名称

index.html

ka-tags.html
{{item}}
app.directive('kaTags',function(){
    return {
        templateUrl:'js/ka-tags.html',
        scope:{
            inputList:'=inputList'
        },
        link:function(){           
        }
    }
})

得到如下:

image.png

一般的业务逻辑都是:选择一些选项,然后将选好的选项发送给后台处理,所以就如上面所说,还需要一个outputList,也就是结果。在angular中,往往是一个controller负责一个业务逻辑,所以我希望输出的时候可以直接让controller得到数据:通常我会在scope上建立一个新的属性用于存放处理后的数据,然后通过ngModel把这个数据与组件抛出来的处理后的数据捆绑到一起,就可以无缝连接了。

$scope.resultList=[];

接下来就是实现组件了,组件内部需要三个List,第一个是用户输入进来的原始List这个list要始终保持不动,第二个是原始List的拷贝,我在实际操作的时候只操作这个拷贝,这样就不会影响用户的原始数据,第三个是输出List,就是用户所有的选择项集合的list。

link:function(scope){
            scope.outputList=[];//用于输出
            scope.oprateInputList=angular.copy(scope.inputList);//用于操作
        }

接下来的事情就很简单了,每当用户选择的时候,就把用户选择的项目从oprateList中删除,加入到outputList中;如果用户从outputList中删除项目,就把删除的项目加入到oprateList中。这样一来就需要两个辅助方法,一个是addItemToArray(item,array),一个是removeItemFromArray(item,array)

link:function(scope,element){
            scope.outputList=[];//用于输出
            scope.oprateInputList=angular.copy(scope.inputList);//用于操作,我不希望影响到用户传入的数组
            scope.addItemToArray=function(item,array){
                array.push(item);
            }
            scope.removeItemFromArray=function(item,array,event){
                var index;
                for(var i=0;i

然后修改一下指令模板就行了

请从下面的标签选择

{{item}}-
{{item}} +

现在就可以实现这种功能了:

image.png

剩下的就是做一个小完善:给组件传入一个值,让组件根据值来显示对象,比如我输入name,就显示人名,输入height,就显示身高

 scope:{
            inputList:'=inputList',
            displayKey:'@'
        },

请从下面的标签选择

{{item[displayKey]}}-
{{item[displayKey]}} +

最后把输出和外面的scope数据绑定一下就行了:

app.directive('kaTags',function($compile,$timeout){
    return {
        templateUrl:'js/ka-tags.html',
        scope:{
            inputList:'=inputList',
            displayKey:'@',
            outputList:'=ngModel'
        },
        link:function(scope,element){
            scope.oprateInputList=angular.copy(scope.inputList);//用于操作,我不希望影响到用户传入的数组
            scope.addItemToArray=function(item,array){
                array.push(item);
            }
            scope.removeItemFromArray=function(item,array,event){
                var index;
                for(var i=0;i

我把demo传到git上面,如果要是有幸能被哪位大哥看到,希望可以指出我的不足,以及指点指点我如何提高自己对组件的认识,谢谢!

github地址

你可能感兴趣的:(用angular写多选组件以及开发时的所思所想)