Пользовательская директива Vue

внешний интерфейс JavaScript Vue.js

предисловие

Vue.js — это прогрессивный фреймворк (официальное описание) для создания пользовательских интерфейсов. С точки зрения непрофессионала, Vue.js — это легкая, простая в использовании, простая в использовании, удобная и гибкая интерфейсная среда MVVM. Краткий API и качественная документация на китайском языке облегчают разработчикам начало работы с платформой Vue.

Эта серия статей объединит некоторый личный опыт (кенг) в использовании Vue (кенг) и некоторые кейсы, выведет некоторые знания о фреймворке Vue, а также закрепит понимание фреймворка Vue.

Пользовательская директива Vue

Кратко

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

Зарегистрировать пользовательскую директиву

Как и компоненты, пользовательские директивы Vue имеют два метода глобальной регистрации и локальной регистрации. Давайте сначала рассмотрим способ регистрации глобальных директив,Vue.directive( id, [definition] )способ зарегистрировать глобальную директиву, первым параметром является имя пользовательской директивы (Имя команды добавлять не нужноv-Префикс, по умолчанию префикс добавляется автоматически, вы должны добавить префикс при использовании команды), вторым параметром могут быть данные объекта или функция инструкции.

<div id="app" class="demo">
    <!-- 全局注册 -->
    <input type="text" placeholder="我是全局自定义指令" v-focus>
</div>
<script>
    Vue.directive("focus", {
        inserted: function(el){
            el.focus();
        }
    })
    new Vue({
        el: "#app"
    })
</script>

В этом простом случае мы регистрируемv-focusКоманда реализует небольшую функцию автоматического разрешения фокусу поля ввода после загрузки страницы. вinsertedЭто функция ловушки пользовательской инструкции, которая будет подробно объяснена позже.

После завершения глобальной регистрации давайте посмотрим, как зарегистрировать локальные пользовательские инструкции, добавив в экземпляр VuedirectivesДанные объекта регистрируют локальные пользовательские директивы.

<div id="app" class="demo">
    <!-- 局部注册 -->
    <input type="text" placeholder="我是局部自定义指令" v-focus2>
</div>
<script>
    new Vue({
        el: "#app",
        directives: {
            focus2: {
                inserted: function(el){
                    el.focus();
                }
            }
        }
    })
</script>

функция ловушки

Объект определения директивы может предоставлять следующие функции ловушек (все необязательные):

  • bind: Вызывается только один раз, когда директива впервые привязывается к элементу. Здесь можно выполнить одноразовые настройки инициализации

  • inserted: вызывается, когда связанный элемент вставляется в родительский узел (гарантируется существование только родительского узла, но не обязательно вставленного в документ).

  • update: вызывается при обновлении VNode компонента, но может произойти до обновления его дочерних VNode. Значение инструкции может измениться, а может и не измениться. Но вы можете игнорировать ненужные обновления шаблона, сравнив значения до и после обновления.

  • componentUpdated: Вызывается после VNode компонента, в котором обновляются инструкция и ее дочерние VNode.

  • unbind: Вызывается только один раз, когда инструкция отсоединяется от элемента.

Этот абзац скопирован из официального документа, я думаю, его следует понять с первого взгляда.

Итак, как использовать эти функции ловушек? Давайте сначала рассмотрим несколько параметров функции ловушки. В функцию хука команды будут переданы следующие параметры:

  • el: Элемент, к которому привязана директива, которую можно использовать для прямого управления DOM, является элементом, на котором размещена директива.

  • binding: Объект, содержащий несколько свойств, которые здесь не описаны, но подробно описаны в официальной документации.

  • vnode: виртуальный узел, сгенерированный компиляцией Vue.

  • oldVnode: Предыдущий виртуальный узел, доступный только в хуках update и componentUpdated.

Пользовательские директивы также могут передавать несколько значений, которые можно передавать с литералами выражений javascript, см. пример:

<div v-demo="{ color: 'white', text: 'hello!' }"></div>
<script>
    Vue.directive('demo', function (el, binding) {
    console.log(binding.value.color) // "white"
    console.log(binding.value.text)  // "hello!"
    })
</script>

Сказав так много теоретических знаний, давайте теперь напишем простой случай. Предположим, вы смотрите на такую ​​сцену:当你在阅览某网站的图片时,可能会由于图片资源比较大而加载缓慢,需要消耗一小段时间来呈现到眼前,这个体验肯定是不太友好的(就像网站切换页面,有时候会加载资源比较慢,为了给用户较好的体验,一般都会先出一个正在加载的友好提示页面),所以这个案例的功能就是在图片资源还没加载出来时,先显示默认背景图,当图片资源真正加载出来了之后,再把真实图片放置到对应的位置上并显示出来。

<div id="app2" class="demo">
    <div v-for="item in imageList">
        <img src="../assets/image/bg.png" alt="默认图" v-image="item.url">
    </div>
</div>
<script>
    Vue.directive("image", {
        inserted: function(el, binding) {
            //为了真实体现效果,用了延时操作
            setTimeout(function(){
                el.setAttribute("src", binding.value);
            }, Math.random() * 1200)
        }
    })
    new Vue({
        el: "#app2",
        data: {
            imageList: [
                {
                    url: "http://consumer-img.huawei.com/content/dam/huawei-cbg-site/greate-china/cn/mkt/homepage/section4/home-s4-p10-plus.jpg"
                },
                {
                    url: "http://consumer-img.huawei.com/content/dam/huawei-cbg-site/greate-china/cn/mkt/homepage/section4/home-s4-watch2-pro-banner.jpg"
                },
                {
                    url: "http://consumer-img.huawei.com/content/dam/huawei-cbg-site/en/mkt/homepage/section4/home-s4-matebook-x.jpg"
                }
            ]
        }
    })
</script>

Интерпретация исходного кода

В библиотеке фреймворка Vuetify есть несколько API-интерфейсов пользовательских директив, включая масштабирование окна браузера.v-resize, полоса прокрутки браузера скользитv-scrollВ ожидании пользовательской команды давайте сейчас изучим исходный код пользовательской команды в Vuetify.

пользовательская директива v-resize

существуетsrc/directives/resize.jsв, даv-resizeОсновной код операции пользовательской инструкции.

function inserted (el, binding) {
    //指令的绑定值,是一个function函数
    const callback = binding.value

    //延时执行函数的毫秒数
    const debounce = binding.arg || 200

    //禁止执行与事件关联的默认动作
    const options = binding.options || { passive: true }

    let debounceTimeout = null
    const onResize = () => {
        clearTimeout(debounceTimeout)
        debounceTimeout = setTimeout(callback, debounce, options)
    }

    //监听窗口缩放
    window.addEventListener('resize', onResize, options)

    //存储监听窗口缩放事件的参数,方便在unbind钩子函数中解除事件绑定的时候使用到
    el._onResize = {
        callback,
        options
    }

    if (!binding.modifiers || !binding.modifiers.quiet) {
        onResize()
    }
}

//绑定的DOM元素被移除时触发
function unbind (el, binding) {
    const { callback, options } = el._onResize

    window.removeEventListener('resize', callback, options)
    delete el._onResize
}

export default {
    //指令名称
    name: 'resize',
    inserted,
    unbind
}

Как видите, определеноinsertedиunbindДве функции ловушки, функция ловушки отмены привязки используется для отмены привязки событий. Во вставленной функции ловушки привязка отслеживает событие масштабирования окна и выполняет функцию обратного вызова, а также использует простую функцию защиты от сотрясения для предотвращения чрезмерной работы.Общий процесс выглядит следующим образом.

Вы можете обнаружить, что приведенный выше код написан в стандартной грамматике es6.Для детской обуви, которые не знакомы с грамматикой es6, это может быть трудно читать, поэтому следующее преобразовано в грамматику es5 для завершения.Чтобы реализовать функцию этой инструкции, рекомендуется как можно лучше ознакомиться со стандартным синтаксисом es6, потому что это неизбежная тенденция в процессе фронтенд-разработки.

function insertedFn (el, binding) {
    var callback = binding.value;
    var debounce = 200;
    var options = {passive: true};
    var debounceTimeout = null;
    var onResize = function () {
        clearTimeout(debounceTimeout);
        debounceTimeout = setTimeout(callback, debounce, options);
    }

    window.addEventListener("resize", onResize, options);

    el._onResize = {
        callback: callback,
        options: options
    };
}

function unbindFn (el, binding) {
    var callback = el._onResize.callback;
    var options = el._onResize.options;
    window.removeEventListener("resize", callback, options);
    delete el._onResize;
}

Vue.directive("resize", {
    inserted: insertedFn,
    unbind: unbindFn
})

Полный кейс можно посмотреть здесь:пользовательская директива v-resize.

Исходный код пользовательских инструкций в Vuetify можно найти на github, прикрепите адрес github Vuetify:GitHub.com/v UE tif аспирант/V….

Суммировать

То, что указано в списке, — это знание некоторых простых пользовательских инструкций Vue, и в реальном проекте будут различные ямы в разных сценариях.
Пользовательские директивы Vue также можно использовать в сценариях, где изображения загружаются лениво,vue-lazyloadЭто использование пользовательских инструкций для ленивой загрузки картинок.По возможности вы можете проанализировать волну позже.vue-lazyloadисходный код.

постскриптум

Статьи написаны в настрое обучения и подведения итогов, на любые ошибки и проблемы в тексте можно указать на github.issues. Все кейсы в этой статье размещены на github по адресу:GitHub.com/Веб-проблема/….