Как сделать небольшую свежую навигацию на JS?

JavaScript

предисловие

В этой статье в основном представлены:

  1. Введение в проект (введение, функция, используемый стек технологий)
  2. Отображение эффекта проекта
  3. Шаг за шагом для достижения эффекта проекта
  4. Ступай на яму

1. Введение проекта

имя:Красивая и быстрая маленькая и свежая навигация

Стек технологий:HTML5, CSS3, JavaScript

Описание функции:

  • Красивая и быстрая персональная навигационная страница с дополнительными основными поисковыми системами.поискФункция
  • URL-адрес навигации привязан к 26 буквам на клавиатуре, и нажатие на буквы на клавиатуре может перейти на соответствующую веб-страницу.
  • Настройте адрес навигации, связанный с буквой, и данные будут сохранены в локальном LocalStorage.
  • На основе собственного JS клавиши клавиатуры генерируются динамически, а стили клавиш полностью дорабатываются с использованием CSS3.

Во-вторых, отображение эффекта проекта

адрес проекта адрес предварительного просмотра

предварительный просмотр

После прочтения предварительного изображения выше, вы немного взволнованы и хотите выбить небольшую свежую навигацию самостоятельно. Приступаем к кодированию!

Три, шаг за шагом для достижения эффекта проекта

(1) Страница анализа

Прежде чем сделать сайт, что такое сайт? писать, рисовать, использоватьдиаграмма вариантов использования, нарисуйте человека, подумайте, какие операции этот человек может делать? Каковы функции пользователей, заходящих на наш сайт?

Что может сделать пользователь:

  • поиск
    • Байду поиск
    • поищите в гугле "если знаете"
  • Введите букву на клавиатуре, чтобы открыть новую страницу
  • Настройте адреса навигации, связанные с буквами

(B) выбор структуры данных

  • q соответствуетqq.com"Хэш"
  • Сохраните структуру клавиатуры в «массиве»

(3) макет HTML

Сначала используйте html напрямую, чтобы обрамить фрейм:

<!DOCTYPE html>
<html lang="zh-Hans">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>小清新导航</title>
    <link rel="stylesheet" href="./css/normalize.css">
    <link rel="stylesheet" href="./css/style.css">
</head>
<body>
    <header>
        <ul>
            <li>
                <a href=""><img src="" alt="google"></a>
            </li>
            <li>
                <a href=""><img src="" alt="百度一下"></a>
            </li>
        </ul>
        <form action="">
            <ul>
                <li>
                    <img src="" alt="google">
                </li>
                <li>
                    <img src="" alt="百度一下">
                </li>
            </ul>
            <input type="text">
            <button></button>
        </form>
    </header>
    <main>
        <div id="main" class="wrapper">
            <div class="row">
                <div class="kbd_wrapper">
                    <kbd>
                        <span>q</span>
                        <img src="" alt="">
                        <button></button>
                    </kbd>
                </div>
            </div>
        </div>
    </main>
    <footer>
        <h3>小Tips</h3>
        <ul>
            <li>1. 按键盘上相应字母进入你想要到的网站</li>
            <li>2. 字母相关的导航地址可将鼠标悬浮其上查看</li>
            <li>3. 鼠标移动到键盘的按键时,可自行编辑导航网址</li>
            <li>4. 编辑后,网址会保留下来,不用担心刷新之后不见了</li>
            <li>5. '.'代表未设置网站或无favicon</li>
        </ul>
    </footer>	
    <script src="./js/main.js"></script>
</body>
</html>

Добавьте класс в тег HTML и добавьте изображение. Примечание: только личные привычки!

<header>
    <ul id="searchEnginPic" class="searchEnginPic">
        <li class="active">
            <a href="https://www.google.com.hk/" target="_blank"><img src="./image/google.png" alt="google"></a>
        </li>
        <li>
            <a href="https://www.baidu.com/" target="_blank"><img src="./image/baidu.gif" alt="百度一下"></a>
        </li>
    </ul>
    <form action="" id="searchBar" class="searchBar">
        <ul id="searchEnginLogo" class="searchEnginLogo">
            <li class="active">
                <img src="./image/google.svg" alt="google">
            </li>
            <li>
                <img src="./image/baidu.svg" alt="baidu">
            </li>
        </ul>
        <input type="text" id="inputBar">
        <button id="searchBtn" class="searchBtn"></button>
    </form>
</header>
<main>
    <div id="main" class="wrapper">
        <div class="row">
            <div class="kbd_wrapper">
                <kbd class="key">
                    <span>q</span>
                    <img src="./image/dot.png" alt="">
                    <button>e</button>
                </kbd>
            </div>
        </div>
    </div>
</main>
<footer class="description">
    <h3>小Tips</h3>
    <ul class="tips-content">
        <li>1. 按键盘上相应字母进入你想要到的网站</li>
        <li>2. 字母相关的导航地址可将鼠标悬浮其上查看</li>
        <li>3. 鼠标移动到键盘的按键时,可自行编辑导航网址</li>
        <li>4. 编辑后,网址会保留下来,不用担心刷新之后不见了</li>
        <li>5. '.'代表未设置网站或无favicon</li>
    </ul>
</footer>

(4) Используйте CSS для украшения интерфейса

1. Украсьте поиск головы

*{margin: 0;padding:0;}
ul{list-style: none;}
.clearfix::after{
    content: '';
    display: block;
    clear: both;
}

/* 注意:这里图片路径是相对路径 */
body{
    background: #ccc url(../image/bg.jpg) no-repeat center center;
    background-size: cover;
}

/* header */
header{
    width: 720px;
    height: 44px;
    margin: 100px auto 50px;
}
header .searchEnginPic{
    float: left;
    width: 120px;
    height: 44px;
}
header .searchEnginPic li{
    display: none;
}
header .searchEnginPic li.active{
    display: inline-block;
}
header .searchEnginPic li:nth-child(1) img{
    width: 120px; 
    padding: 2.5px 0;
}
header .searchEnginPic li:nth-child(2) img{
    width: 120px; 
    height: 44px;
}

header .searchBar{
    float: right;
    width: 580px;
    height: 44px;
    border-radius: 24px;
    position: relative;
    background: #fff;
}
header .searchBar:hover{
    box-shadow: 0 1px 6px 0 rgba(32,33,36,0.28);
    border-color: rgba(223,225,229,0);
}
header .searchBar .searchEnginLogo{
    position: absolute;
    left: 10px;
    width: 24px;
    height: 44px;
    cursor: pointer;
}
header .searchBar .searchEnginLogo li{
    display: none;
}
header .searchBar .searchEnginLogo li.active{
    display: inline-block;
}
.searchBar .searchEnginLogo li img{
    width: 24px;
    height: 24px;
    padding: 10px 0;
}
.searchBar input{
    position: absolute;
    left: 46px;
    top: 10%;
    width: 505px;
    height: 80%;
    border: none;
    outline: none;
}
.searchBar .searchBtn{
    position: absolute;
    right: 6px;
    top: 7px;
    width: 30px;
    height: 30px;
    background: url(../image/search-btn.png) center center no-repeat;
    cursor: pointer;
    border: none;
    outline: none;
}

2. Добавляем стили к клавишам клавиатуры

/* main */
.wrapper div{
    width: 850px;
    margin: 0 auto;
    text-align: center;
}
.wrapper .kbd_wrapper{
    display: inline-block;
    vertical-align: top;
    width: 65px;
    height: 55px;
    border-radius: 7px;
    margin: 6px;
    box-shadow: 0 4px 3px 0 #3C3C3D, 0 0 1px 0 #3C3C3D;
    text-align: center;
}
.wrapper kbd{
    position: relative;
    display: inline-block;
    width: 65px;
    height: 50px;
    background: linear-gradient(to bottom, #fff 0%,#fff 70%,#f3f3f3 100%);
    border-radius: 7px;
    box-shadow: 0 5px 0 0 #767d81;
    color: #767D81;
    font-family: Helvetical;
    vertical-align: top;
    line-height: 50px;
    text-transform: uppercase;
    font-weight: bold;
    transition: all .2s linear;
}
.wrapper .kbd_wrapper:hover {
    cursor: pointer;
    animation: shake 0.82s cubic-bezier(.36, .07, .19, .97) both;
    transform: translate3d(0, 0, 0);
    backface-visibility: hidden;
    perspective: 1000px;
}
.wrapper kbd > button{
    display: none;
    position: absolute;
    right: 2px;
    bottom: 2px;
    font-size: 12px;
    width: 16px;
    height: 16px;
    border-radius: 5px;
    border: none;
    outline: none;
    color: #333;
    cursor: pointer;
}
.wrapper kbd:hover > button{
    display: inline-block;
}
.wrapper kbd > button:hover{
    background: #806605;
    color: #fff;
}
.key img{
    width: 16px;
    height: 16px;
    position: absolute;
    left: 4px;
    bottom: 2px;
}
@keyframes shake {
    10%, 90% {
        transform: translate3d(-1px, 0, 0);
    }
    20%, 80% {
        transform: translate3d(2px, 0, 0);
    }
    30%, 50%, 70% {
        transform: translate3d(-4px, 0, 0);
    }
    40%, 60% {
        transform: translate3d(4px, 0, 0);
    }
}

3. Украсить нижние кончики

/* footer */
footer{
    width: 390px;
    margin: 50px auto 0;
}
footer h3{
    margin-bottom: 10px;
}
footer .tips-content li{
    padding: 3px 0;
}

(5) Используйте JS для создания HTML, добавляйте события для достижения эффектов

1. Инициализировать данные

При инициализации данных нужно получить хэш, соответствующий данным в localStorage

//1.初始化数据
let hashA = init();
let keys = hashA['keys'];
let hash = hashA['hash'];

// 下面是工具函数
function init(){
    let keys = {
        0 : ['q','w','e','r','t','y','u','i','o','p'],
        1 : ['a','s','d','f','g','h','j','k','l'],
        2 : ['z','x','c','v','b','n','m'],
        length : 3
    }
    let hash = {
        q : 'qq.com',
        w : 'wangdoc.com',
        e : undefined,
        r : 'react-juejin.foreversnsd.cn',
        t : 'tgideas.qq.com/doc/',
        y : 'youtube.com',
        i : 'iciba.com',
        o : undefined,
        p : undefined,
        a : undefined,
        s : 'segmentfault.com',
        d : 'dribbble.com',
        f : undefined,
        g : 'github.com',
        h : undefined,
        j : 'juejin.im',
        k : 'ke.qq.com',
        l : undefined,
        z : 'zhihu.com',
        x : 'xiedaimala.com',
        c : 'csdn.net',
        v : undefined,
        b : 'bilibili.com',
        n : undefined,
        m : 'mail.163.com'
    }
    let hasInLocalStorage = getFormLocalStorage('data');
    if(hasInLocalStorage){
        hash = hasInLocalStorage;
    }
    return {'keys':keys,'hash':hash}
}

function getFormLocalStorage(name){
    return JSON.parse(localStorage.getItem(name) || 'null')
}

2. Сгенерируйте клавиатуру

Не забудьте удалить содержимое div, чей класс является оболочкой, и используйте js для генерации html.

//2.生成键盘
generateKeyBoard(keys,hash);

function generateKeyBoard(keys, hash) {
    for (let index = 0; index < keys['length']; index = index + 1) { //0 1 2
        let div = tag('div');
        main.appendChild(div);

        let row = keys[index];
        for (let index2 = 0; index2 < row['length']; index2 = index2 + 1) { //将固定的10换成可控制的
            let kbd_wrapper = tag('div');
            kbd_wrapper.className = 'kbd_wrapper';
            let kbd = tag('kbd');
            kbd.className = 'key';
            let span = createSpan(row[index2]);
            let img = createImage(hash[row[index2]]);
            let button = createButton(row[index2]);
        
            // 判断按键是否已经有对应的网址
            if (hash[row[index2]] === undefined) {
                kbd.setAttribute('title', '未设置网站导航');
            } else {
                kbd.setAttribute('title', hash[row[index2]]);
            }

            kbd.onclick = function (e) {
                let website = e.currentTarget.getAttribute('title');
                if (website === '未设置网站导航') {
                    alert('请编辑此按键的网站再跳转');
                } else {
                    window.open('http://' + website, "_blank");
                }
            }
            
            kbd.appendChild(span);
            kbd.appendChild(img);
            kbd.appendChild(button);
            kbd_wrapper.appendChild(kbd);
            div.appendChild(kbd_wrapper);
        }
    }
}

function tag(tagName) {
    let element = document.createElement(tagName);
    return element;
}

function createSpan(textContent) {
    let span = tag('span');
    span.textContent = textContent; //第一个数组 第二个数组 第三个数组
    span.className = 'text';
    return span;
}

function createButton(id) {
    let button = tag('button');
    button.textContent = 'e';
    button.id = id;
    button.onclick = function (e) {
        //阻止事件冒泡
        e.stopPropagation();
        let button2 = e['target'];
        let img2 = button2.previousSibling;
        //获取当前的id
        let key = button2['id'];
        //用户输入一个网址
        let web = prompt('请输入一个网址:');
        //将原来的hash给替换掉
        hash[key] = web;
        img2.src = 'http://' + web + '/favicon.ico';
        console.log(e.target)
        img2.onerror = function (e) {
            e.target.src = './image/dot.png';
        }
        localStorage.setItem('data', JSON.stringify(hash));
    }
    return button;
}

function createImage(domain) { //hash[row[index2]]
    let img = tag('img');
    if (domain) {
        img.src = 'http://' + domain + '/favicon.ico';
    } else {
        img.src = './image/dot.png';
    }
    img.onerror = function (e) {
        e.target.src = './image/dot.png';
    }
    return img;
}

3. Следите за действиями пользователей

//3.监听用户动作
listenToUser(hash);
switchSearchEngin();

function listenToUser(hash) {
    // ifInputting作为一个开关
    let ifInputting = false;
    let inputBar = document.getElementById('inputBar');
    let searchBtn = document.querySelector('.searchBtn');
    inputBar.addEventListener('focus', function (e) {
        ifInputting = true;
        e.target.placeholder = '';
    })
    inputBar.addEventListener('focusout', function (e) {
        ifInputting = false;
        e.target.placeholder = '点击左边图标切换搜索引擎';
    })
    searchBtn.onclick = function (e) {
        e.preventDefault();
        let searchContent = inputBar.value;
        // 判断是什么搜索引擎
        let searchEnginLogo = document.getElementById('searchEnginLogo');
        let engin = searchEnginLogo.getAttribute('data-engin');
        switch (engin) {
            case 'baidu':
                window.open("https://www.baidu.com/s?wd=" + searchContent, '_blank');
                break;
            case 'google':
                window.open("https://www.google.com.hk/search?q=" + searchContent, '_blank');
                break;
        }
    }

    document.onkeypress = function (e) {
        let key = e['key'];
        let website = hash[key];
        if (!ifInputting) {
            if (website === undefined) {
                alert('请编辑此按键的网站再跳转')
            } else {
                window.open('http://' + website, "_blank");
            }
        }
    }
}

// 切换搜索引擎
function switchSearchEngin() {
    // 搜索引擎默认是google
    let ifSwitch = false;
    let searchEnginLogo = document.getElementById('searchEnginLogo');
    let googleLogo = document.querySelector('#searchEnginLogo li:nth-child(1)');
    let baiduLogo = document.querySelector('#searchEnginLogo li:nth-child(2)');
    let googlePic = document.querySelector('#searchEnginPic li:nth-child(1)');
    let baiduPic = document.querySelector('#searchEnginPic li:nth-child(2)');
    searchEnginLogo.setAttribute('data-engin', 'google');
    searchEnginLogo.onclick = function () {
        if (!ifSwitch) {
            // google --> baidu
            googleLogo.classList.remove('active');
            baiduLogo.classList.add('active');
            googlePic.classList.remove('active');
            baiduPic.classList.add('active');
            searchEnginLogo.setAttribute('data-engin', 'baidu');
        } else {
            // baidu --> google
            baiduLogo.classList.remove('active');
            googleLogo.classList.add('active');
            baiduPic.classList.remove('active');
            googlePic.classList.add('active');
            searchEnginLogo.setAttribute('data-engin', 'google');
        }
        ifSwitch = !ifSwitch;
    }
}

Ступай на яму

(1) Вопрос 1 Существует конфликт между вводом в поле поиска и нажатием кнопки для перехода

Решение:

Определите переменную (логического типа) как переключатель, который превращает эту переменную в истину, когда ввод получает фокус, и превращает эту переменную в ложь, когда ввод теряет фокус. В то же время, когда событие запускается, эта переменная оценивается, чтобы понять, хочет ли пользователь ввести текстовый поиск или нажать кнопку, чтобы перейти на нужную веб-страницу. Более подробный код см. в коде выше или на github.

let ifInputting = false;
let inputBar = document.getElementById('inputBar');
let searchBtn = document.querySelector('.searchBtn');
inputBar.addEventListener('focus', function (e) {
    ifInputting = true;
    e.target.placeholder = '';
})
inputBar.addEventListener('focusout', function (e) {
    ifInputting = false;
    e.target.placeholder = '点击左边图标切换搜索引擎';
})

document.onkeypress = function (e) {
    let key = e['key'];
    let website = hash[key];
    if (!ifInputting) {
        if (website === undefined) {
            alert('请编辑此按键的网站再跳转')
        } else {
            window.open('http://' + website, "_blank");
        }
    }
}

(2) Вопрос 2: В чем разница между e.currentTarget и e.target, захватом и всплытием?

Блог, который я создал раньшеГлубокое понимание механизма событий DOMКасательно содержания вопроса 2, вот вам небольшая хитрость: ctrl+f, вы можетеПоиск в Интернете по ключевым словам.

(3) При нажатии кнопки редактирования после ввода URL-адреса нажмите «ОК», откроется новая веб-страница. Почему?

Решение: на самом деле из-за всплытия события срабатывает событие щелчка kbd, поэтому необходимо только предотвратить всплывание события.