angularjs随笔 -- angularjs使用自定义指令封装下拉框

angularjs使用自定义指令封装下拉框

  • 1. 效果图如下:
  • 2. 代码如下:
  • 3. 封装组件总结:

angularjs 核心部分在自定义指令的使用,本文以封装下拉框为例做介绍,其他组件封装方法类似,有需要的请自行扩展。

1. 效果图如下:

angularjs随笔 -- angularjs使用自定义指令封装下拉框_第1张图片

2. 代码如下:

<!DOCTYPE html>
<html lang="en" ng-app="myApp">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        * {
            margin: 0;
            padding: 0;
        }

        ul {
            list-style: none;
        }

        ::-webkit-scrollbar {
            width: 8px;
            height: 8px;
        }

        ::-webkit-scrollbar-thumb {
            background-color: #c1c1c1;
            -webkit-border-radius: 6px;
            border-radius: 6px;
        }

        ::-webkit-scrollbar-track-piece {
            background-color: #f4f6fa;
        }

        ::-webkit-scrollbar-button {
            display: none;
        }

        .self-dropdown-box {
            display: inline-block;
            width: 200px;
            position: relative;
            font-size: 14px;
            color: #666;
            margin: 20px 10px;
        }

        .self-dropdown-box .self-dropdown-title {
            height: 30px;
            border: 1px solid #ccc;
            cursor: pointer;
            border-radius: 2px;
            padding: 0 12px;
            line-height: 28px;
            white-space: nowrap;
            overflow: hidden;
            text-overflow: ellipsis;
            user-select: none;
            position: relative;
            padding-right: 24px;
        }

        .self-dropdown-box .self-dropdown-title .self-dorpdown-icon {
            position: absolute;
            right: 12px;
            top: 12px;
            width: 0;
            height: 0;
            border: 4px solid transparent;
            border-top-color: #000;
            transform: rotate(0deg);
            transform-origin: 50% 30%;
            transition: all 0.5s;
        }

        .self-dropdown-box.showPanel .self-dropdown-title .self-dorpdown-icon {
            transform: rotate(180deg);
            transform-origin: 50% 30%;
        }

        .self-dropdown-box .self-dropdown-panel {
            position: absolute;
            left: 0;
            top: 31px;
            width: 200px;
            max-height: 200px;
            overflow: auto;
            border: 1px solid #ccc;
            box-sizing: border-box;
            border-radius: 0 0 2px 2px;
            display: none;
            z-index: 99;
        }

        .self-dropdown-box .self-dropdown-panel li {
            padding: 6px 12px;
            cursor: pointer;
            transition: background-color .3s;
            word-break: break-all;
        }

        .self-dropdown-box .self-dropdown-panel li:hover {
            background: #f2f5fa;
        }
    </style>
</head>

<body ng-controller="testDropdown">
    <div class="drop-test">
    	
        <drop-down selectval="dropdownSelectVal" dropdowndata="dropdownListObj.dropdownList" valChange="changeSelect()">
        </drop-down>

        <drop-down selectval="dropdownSelectVal2" dropdowndata="dropdownListObj2.dropdownList"
            valChange="changeSelect()">
        </drop-down>
    </div>
</body>
<script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
<script src="http://apps.bdimg.com/libs/angular.js/1.4.6/angular.min.js"></script>
<script>
    // 创建主模块
    var myApp = angular.module('myApp', []);

    // 创建controller
    myApp.controller('testDropdown', ['$scope', '$timeout', function ($scope, $timeout) {

        $scope.dropdownListObj = {
            dropdownList: []
        };

        $timeout(function () {
            // 模拟数据加载
            $scope.dropdownListObj.dropdownList = ['数据1', '数据2', '数据3', '数据4', '数据5', '数据6', '数据7',
                '数据8'
            ];
        }, 1000);

        $scope.dropdownSelectVal = '';

        $scope.changeSelect = function () {
            console.log($scope.dropdownSelectVal);
        }

        // 创建两个组件测试是否互相影响
        $scope.dropdownSelectVal2 = '';

        $scope.dropdownListObj2 = {
            dropdownList: ['我们是第二组数据1,我的长度特别长长长长长长长长长长长长', '我们是第二组数据2', '我们是第二组数据3', '我们是第二组数据4',
                '我们是第二组数据5', '我们是第二组数据6'
            ]
        };

    }]);

    // 下拉框组件自定义指令
    myApp.directive('dropDown', [function ($timeout) {
        return {
            restrict: 'E', // 指令采用元素展示
            replace: true, // 模板内容对指令进行替换
            transclude: true, // 开启 ng-transclude ,及将xxx指令中间内容插入到模板有ng-transclude标识的元素中
            scope: { // 与controller的交互,需要重点关注
                selectval: '=', // 默认值, '=' 代表双向相应,及指令与controller交互方式
                dropdowndata: '=', // 下拉面板数据
                valChange: '&', // 选项变化时事件, 代表调用 controller 的方法
                placeholder: '@', // 代表单向获取数据,
            },
            templateUrl: './dropdownTpl.html', // HTML模板
            link: function ($scope, $element,
            $attrs) { // scope 代表上述衍生的作用域,$element 代表绑定的元素,$attrs 代表绑定元素的属性

                $scope.showPanel = false;

                $scope.toggle = function () {
                    $scope.showPanel = !$scope.showPanel;
                    if ($scope.showPanel) {
                        $($element).find('.self-dropdown-panel').slideDown();
                    } else {
                        $($element).find('.self-dropdown-panel').slideUp();
                    }
                };

                $scope.clickitem = function (data) {
                    $scope.selectval = data;
                    $scope.showPanel = !$scope.showPanel;
                    if ($scope.showPanel) {
                        $($element).find('.self-dropdown-panel').slideDown();
                    } else {
                        $($element).find('.self-dropdown-panel').slideUp();
                    }
                };

                $scope.$watch('selectval', function (value) {
                    $scope.valChange();
                });

                // 点击空白部分让下拉面板收起
                document.addEventListener('click', function (e) {
                    if ($element[0].contains(e.target)) {
                        return false;
                    }
                    $scope.showPanel = false;
                    // 解决双向数据绑定不生效
                    if (!$scope.$$phase) {
                        $scope.$apply();
                    }
                    $($element).find('.self-dropdown-panel').slideUp();
                });
            }
        };
    }]);
</script>

</html>

dropdownTpl.html 代码如下:

<div class="self-dropdown-box" ng-class="{'showPanel': showPanel }">
    <div class="self-dropdown-title" ng-click="toggle()">
        <span title="{{selectval}}" ng-bind="selectval"></span>
        <span class="self-dorpdown-icon"></span>
    </div>
    <ul class="self-dropdown-panel">
        <li ng-repeat="data in dropdowndata" ng-click="clickitem(data)">{{data}}</li>
    </ul>
</div>

3. 封装组件总结:

  1. 考虑都需要给指令传递哪些参数,是否需要进行双向响应;
  2. 传值中 ‘=’ 代表双向响应; ‘@’ 代表单向数据获取; ‘&’ 代表需要调用父 controller 中的方法;
  3. 需要考虑其可扩展性与可维护性,注释代码一定要清晰明了。

你可能感兴趣的:(angularjs)