전단 팁: 원본 js로 창 메시지 알림 플러그인 쓰기

18692 단어
여보세요, 여기는 참깨입니다. 오늘 우리 함께 '탄창 메시지 알림' 플러그인을 만듭시다.자, 바로 이런 효과다.
1. 분석
  • 은 소식이 촉발될 때 위에서 아래로 담입하는 과정이 있다.
  • 은 일정 시간 지속되면 자동으로 사라지거나 사용자가 수동으로 닫기 버튼을 눌러야 한다.
  • 은 소식이 사라질 때 아래에서 위로 담출되는 과정이 있다.
  • 메시지는 겹쳐서 팝업할 수 있으며 최신 메시지는 메시지 목록의 맨 뒤에 있습니다.
  • 앞의 소식이 사라지면 뒤의 소식이 위로 미끄러지는 효과가 있다.

  • 그리고 소식 자체가 세 부분으로 이루어져 있어요.
  • 메시지 아이콘으로 다양한 종류의 메시지를 구분합니다.
  • 메시지 텍스트
  • 닫기 버튼, 모든 메시지를 닫아야 하는 것은 아닙니다.

  • 2. 스타일 구현
    그러면 우리가 원생 js를 사용하든지 vue를 사용하든지, 우선, 우리는 이 메시지의 기본 양식을 쓴 다음에 js를 통해 메시지의 팝업과 닫기를 제어해야 한다.그래서 우리는 먼저 html과 css를 쓴다.
    
    
    
    "stylesheet" href="http://at.alicdn.com/t/font_1117508_wxidm5ry7od.css">
    "stylesheet" href="./message.css">
    "./message.js"</span>>
    
    
    
    "message-container">
    "message">
    "type icon icon-success">
    "text"> ~
    "close icon icon-close">
    "message">
    "type icon icon-error">
    "text"> ~
    /* message.css */
    
    #message-container {
        position: fixed;
        left: 0;
        top: 0;
        right: 0;
    
        /*   flex    ,                ,          */
        display: flex;
        flex-direction: column;
        align-items: center;
    }
    #message-container .message {
        background: #fff;
        margin: 10px 0;
        padding: 0 10px;
        height: 40px;
        box-shadow: 0 0 10px 0 #eee;
        font-size: 14px;
        border-radius: 3px;
    
        /*           (  、  、    )         */
        display: flex;
        align-items: center;
    }
    #message-container .message .text {
        color: #333;
        padding: 0 20px 0 5px;
    }
    #message-container .message .close {
        cursor: pointer;
        color: #999;
    }
    
    /*              ,            */
    #message-container .message .icon-info {
        color: #0482f8;
    }
    #message-container .message .icon-error {
        color: #f83504;
    }
    #message-container .message .icon-success {
        color: #06a35a;
    }
    #message-container .message .icon-warning {
        color: #ceca07;
    }
    #message-container .message .icon-loading {
        color: #0482f8;
    }
    

    이런 효과인 것 같아요.
    3. 애니메이션 구현
    다음에 해야 할 일은 이 메시지의 팝업과 사라짐 애니메이션입니다. 우리는 css로 실현합니다.
    css에서 사용자 정의 애니메이션을 실현하려면 @keyframes로 애니메이션 규칙을 정의한 다음 애니메이션 속성을 통해 애니메이션을 요소에 적용하면 됩니다.
    이른바 애니메이션 규칙이란 하나의 애니메이션 서열이나 하나의 관건적인 프레임으로 이해할 수 있다. 관건적인 프레임의 내부는 바로 당신이 바꾸고 싶은 css 속성이다. 당신은 관건적인 프레임에 거의 모든 css 속성을 쓸 수 있다. 애니메이션이 응용될 때 이런 css 속성은 각 관건적인 프레임에 따라 상응하는 변환을 한다.
    그러면 @keyframes로 애니메이션 룰을 한번 써보도록 하겠습니다.
    /* message.css */
    
    /*            message-move-in ,      animation                。 */
    @keyframes message-move-in {
        0% {
            /*       ,                 */
            /*                      0,                1,             */
            opacity: 0;
            /*   “    ”       “transform”        “translateY”          */
            /* translateY(-100%)        ,         “      ”   。 */
            transform: translateY(-100%);
        }
        100% {
            opacity: 1;
            /*         */
            transform: translateY(0);
        }
    }
    

    그리고 우리는 message 요소와 같은 등급의 클래스 move-in을 다시 정의했다. message-move-in이라는 애니메이션 규칙을 move-in 클래스에 적용했다. 그러면 우리는 어떤 메시지를 팝업해야 하는지 메시지의 클래스에 move-in을 추가하면 된다.
    /* message.css */
    
    #message-container .message.move-in {
        /* animation                  https://developer.mozilla.org/zh-CN/docs/Web/CSS/animation */
        animation: message-move-in 0.3s ease-in-out;
    }
    
    move-in:
    어떤 메시지에 move-in을 추가하면 팝업 애니메이션을 만들 수 있음을 알 수 있다.그러면 애니메이션을 사라지는 것도 하나의 방법이다. 단지 팝업 애니메이션과 반대일 뿐이다.
    /* message.css */
    
    @keyframes message-move-out {
        0% {
            opacity: 1;
            transform: translateY(0);
        }
        100% {
            opacity: 0;
            transform: translateY(-100%);
        }
    }
    
    #message-container .message.move-out {
        animation: message-move-out 0.3s ease-in-out;
        /*              */
        animation-fill-mode: forwards;
    }
    
    animation-fill-mode: forwards; 이거 뭐 하는 거예요?애니메이션이 끝나면 기본적으로 요소의 초기 상태로 돌아가기 때문에 그림과 같이 사라진 후에 다시 나타난다.
    그래서 animation-fill-mode: forwards;은 애니메이션이 끝난 후에 이 종료 상태를 유지하기 위해 표시되지 않는다.
    4. js 플러그인 작성
    그럼 js를 쓰기 전에 먼저 생각해 봅시다. 만약에 당신이 플러그인의 사용자라면 이 플러그인을 어떻게 호출하고 싶습니까?
    우리의 플러그인은 매우 간단하다. 바로 필요할 때 메시지를 팝업하는 것이다. 만약에 플러그인이 우리에게 제공한 클래스가 Message이라고 가정하자. 그리고 그의 내부에 show 방법이 하나 있다. 그러면 사용자가 이 클래스를 실례화한 후에 그의 show 방법을 사용하고 서로 다른 매개 변수를 보내면 메시지를 팝업할 수 있다.그리고 우리가 실례화한 대상은 전체적으로 유일할 수 있다.
    
    
    
    
    // message         ,         。
    const message = new Message();
    message.show({
        <span class="hljs-built_in">type</span>: <span class="hljs-string">'success'</span>,
        text: <span class="hljs-string">'       ~'</span>
    });
    
    

    그래서 우리는 먼저 메시지 종류를 쓰고 show 방법을 실현해야 한다.
    /* message.js */
    
    class Message {
        constructor() {
    
        }
    
        show({ type = 'info', text = '' }) {
    
        }
    }
    

    여기서 저는 에스6의 class 키워드를 직접 사용했는데 사실 그의 내부는 원형 체인의 형식입니다.class으로 이 종류를 더욱 직관적으로 이해할 수 있습니다.
    우리가 첫 번째 부분에서 분석한 바와 같이 모든 메시지 요소는 js에서 만들어야 하기 때문에 사용자가 어떤 html 코드를 쓸 필요가 없다. 그러면 우리는 대상이 실례화될 때 메시지 용기 new Message()을 만들고 message-container 방법을 호출할 때 메시지를 show 내부에 직접 삽입하면 된다.
    /* message.js */
    
    class Message {
    
        /**
         *                 
         */
        constructor() {
            const containerId = 'message-container';
            //    html        message-container  
            this.containerEl = document.getElementById(containerId);
    
            if (!this.containerEl) {
                //     Element  ,       id message-container dom  
                this.containerEl = document.createElement('div');
                this.containerEl.id = containerId;
                //  message-container    html body  
                document.body.appendChild(this.containerEl);
            }
        }
    
        show({ type = 'info', text = '' }) {
    
        }
    }
    

    이렇게 하면 message-container을 호출할 때dom에 const message = new Message() 노드를 자동으로 삽입합니다.그렇다면 가장 중요한 것은 우리의 message-container 방법입니다.
  • 에서 메시지 노드를 만들고 show 용기의 끝까지 추가합니다.
  • 은 이 시간이 끝난 후에 자동으로 메시지를 제거할 시간을 설정합니다.
  • 은 "닫기 단추"의 message-container 이벤트를 감청하여 사용자가 수동으로 메시지를 제거할 수 있도록 합니다.

  • 우리 한 걸음 한 걸음 하자.
    4.1 메시지 노드를 만들고 click 용기의 끝까지 추가합니다.
    class Message {
    
        //   ...
    
        show({ type = 'info', text = '' }) {
            //     Element  
            let messageEl = document.createElement('div');
            //     class,    move-in          
            messageEl.className = 'message move-in';
            //     html   
            messageEl.innerHTML = `
                "icon icon-${type}">
                
    "text">${text}
    "close icon icon-close">
    `; // message-container // this.containerEl message-container this.containerEl.appendChild(messageEl); }

    한번 모셔보도록 하겠습니다.
    
    
    
    
        
    
        
            // message         ,         。
            const message = new Message();
            document.querySelector(<span class="hljs-string">'.btn'</span>).addEventListener(<span class="hljs-string">'click'</span>, () => {
                message.show({
                    <span class="hljs-built_in">type</span>: <span class="hljs-string">'success'</span>,
                    text: <span class="hljs-string">'       ~'</span>
                });
            });
            
        
    

    4.2 이 시간이 끝나면 자동으로 메시지를 제거할 시간을 설정합니다.
    // message.js
    
    class Message {
    
        //   ...
    
        show({ type = 'info', text = '', duration = 2000 }) {
            //   ...
    
            //  setTimeout       
            setTimeout(() => {
                // Element       remove  ,           dom    !
                messageEl.remove();
            }, duration);
        }
    }
    

    보시다시피 메시지가 2초가 지난 후에 자동으로dom트리에서 제거되었습니다. 그러나 애니메이션이 없습니다. 앞에서 우리가 쓴 것을 기억합니다.message-container류요?이런 종류와move-out은 동급이다.지금 우리는 정해진 시간에 이 종류를 적용하기만 하면 된다message 원소에 넣으면 됩니다.
    // message.js
    
    class Message {
    
        //   ...
    
        show({ type = 'info', text = '', duration = 2000 }) {
            //   ...
    
            //  setTimeout       
            setTimeout(() => {
                //    move-in           ,       ,       
                messageEl.className = messageEl.className.replace('move-in', '');
                //     move-out 
                messageEl.className += 'move-out';
    
                //              ,          dom    。
                //        move-out     messageEl.remove,             
                messageEl.addEventListener('animationend', () => {
                    // Element       remove  ,           dom    !
                    messageEl.remove();
                });
            }, duration);
        }
    }
    

    dom트리의 변화를 주의 깊게 관찰하기:
    4.3'닫기 단추'의 message 이벤트를 감청하여 사용자가 수동으로 메시지를 제거할 수 있도록 한다.
    때때로 사용자가 수동으로 닫을 때까지 메시지를 계속 보여 주기를 바랍니다. 우선 이 닫기 단추를 보여 줄지 여부를 제어하기 위해 파라미터를 추가해야 합니다.
    // message.js
    
    class Message {
    
        //   ...
    
        show({ type = 'info', text = '', duration = 2000, closeable = false }) {
            //     Element  
            let messageEl = document.createElement('div');
            //     class,    move-in          
            messageEl.className = 'message move-in';
            //     html   
            messageEl.innerHTML = `
                "icon icon-${type}">
                
    "text">${text}
    `; // if (closeable) { // let closeEl = document.createElement('div'); closeEl.className = 'close icon icon-close'; // message messageEl.appendChild(closeEl); // click , close // close closeEl.addEventListener('click', () => { this.close(messageEl) }); } // message-container // this.containerEl message-container this.containerEl.appendChild(messageEl); // duration 0 , if (duration > 0) { // setTimeout setTimeout(() => { this.close(messageEl); }, duration); } } /** * * , , * @param {Element} messageEl */ close(messageEl) { // move-in , , messageEl.className = messageEl.className.replace('move-in', ''); // move-out messageEl.className += 'move-out'; // , dom 。 // move-out messageEl.remove, messageEl.addEventListener('animationend', () => { // Element remove , dom ! messageEl.remove(); }); } }

    한번 모셔보도록 하겠습니다.
    
    
    
    
        
    
        
            // message         ,         。
            const message = new Message();
            document.querySelector(<span class="hljs-string">'.btn'</span>).addEventListener(<span class="hljs-string">'click'</span>, () => {
                message.show({
                    <span class="hljs-built_in">type</span>: <span class="hljs-string">'warning'</span>,
                    text: <span class="hljs-string">'         '</span>,
                    duration: 0,    //       
                    closeable: <span class="hljs-literal">true</span>, //      
                });
            });
            
        
    

    사실은 이미 쓴 것이 많지 않지만 작은 문제가 있다. 예를 들어 우리가 두 개, 심지어 더 많은 소식을 꺼낼 때 앞의 소식이 사라지면 아래의 소식은 바로 위의 위치로 올라가 경직되고 아무런 미끄럼도 없다. 그림과 같다.
    우리는 css의 click 속성을 통해 transition의 높이를 점점 작게 할 수 있다. 그러면 아래의 원소는 변화에 따라 점차적으로 위로 이동할 수 있다.
    /* message.css */
    /*   ... */
    
    #message-container .message {
        background: #fff;
        margin: 10px 0;
        padding: 0 10px;
        height: 40px;
        box-shadow: 0 0 10px 0 #ccc;
        font-size: 14px;
        border-radius: 3px;
    
        /*           (  、  、    )         */
        display: flex;
        align-items: center;
        
        /*         , message      margin              */
        transition: height 0.2s ease-in-out, margin 0.2s ease-in-out;
    }
    
    /*   ... */
    

    Message 클래스의 close 방법을 변경하기만 하면 됩니다.
        close(messageEl) {
            //    move-in           ,       ,       
            messageEl.className = messageEl.className.replace('move-in', '');
            //     move-out 
            messageEl.className += 'move-out';
    
            // move-out                  0
            //      css    transition  ,          
            messageEl.addEventListener('animationend', () => {
                messageEl.setAttribute('style', 'height: 0; margin: 0');
            });
    
            //        transition         ,          dom    。
            messageEl.addEventListener('transitionend', () => {
                // Element       remove  ,           dom    !
                messageEl.remove();
            });
        }
    

    효과 보기:
    엔딩
    자, 기본적으로 다 썼지만 각 브라우저의 호환성을 위해 meesage로 코드를 바꾸는 것을 권장합니다. 발표하려면 babel으로 js와 css를 함께 포장할 수 있습니다.
    그러나 우리는 한 장면을 적게 고려했다. 현재의 폐쇄 메시지는 모두 대상 내부에서 webpack 방법을 사용해서 이루어진다. 만약에 외부에서 메시지의 폐쇄를 제어할 수 있기를 희망한다면 예를 들어 내가 서버에 요청할 때 close의 메시지를 팝업하고 현재 서비스기가 데이터를 되돌려준 후에 나는 어떻게 이 메시지를 닫을 것인가.간단합니다. 여러분 스스로 실현하세요!
    여기 보니까 팔로우 하나 못 눌러요?

    좋은 웹페이지 즐겨찾기