предисловие
В обычном процессе разработки мы всегда сначала пишем компонент, а потом используем его в нужной странице.importЕго можно импортировать, но что делать, если это компонент следующего типа👇Вышеупомянутый тип приглашения с плавающим слоем имеет замечательную особенность, то есть частота использования очень высока, почти каждая страница будет использовать его, поэтому нам нужно ввести этот компонент на каждой странице, и на каждой странице его нужно контролировать. переменной, что явно не то, что нам нужно🙅. . . Так чего же мы хотим🤔? Студенты, которые использовали некоторые фреймворки пользовательского интерфейса, должны знать, что существует такое использование:
this.$toast({
duration: 3000,
content: '这是一条消息提示'
});
Правильно, с таким простым предложением все будет хорошо (просто используйте js для вызова компонентов 🧐). Так как же достигается этот эффект? Давайте (руки об руку 🤝) узнаем сегодня!
Предварительное знание
Я не знаю, маленькие друзья не были использованыVue.extend()Во всяком случае, я редко прикасался к этому материалу, и он меня не впечатлил, так что давайте сначала кратко его рассмотрим.Vue.extend()Главное за что. Начнем с официального описания (не многого, придерживайтесь его):Не понимаю? 😴Не беда, не беда, просто нужно запомнить (с небольшим пониманием) следующее употребление:
// 导入以往的普通组件
import Main from './main.vue';
// 用 Vue.extend 创建组件的模板(构造函数)
let mainConstructor = Vue.extend(Main);
// 实例化组件
let instance = new mainConstructor();
// 挂载到相应的元素上
instance.$mount('#app');
Я не знаю, понимаете ли вы, что вышеVue.extend(Main)Это шаблон компонента (конструктор) на основе main.vue,instanceявляется экземпляром компонента,$mount()Вручную монтировать смысл. вVue.extend()а также$mount()Это суть того, как мы вызываем, визуализируем и монтируем компоненты через js, что эквивалентно предыдущемуcreateElementа такжеappendChild, имеют тот же эффект. Этот момент требует от нас знакомства с ним, чтобы вы могли остановиться и подумать снова и снова🤔.
Чтобы добавить 🤐:$mount()Если в нем нет параметров, значит компонент только отрисовывается, но еще не монтируется на страницу, если есть правильные (элементные) параметры, то он будет монтироваться непосредственно под элемент.
Написать компонент всплывающего уведомления
js вызываются, и еще требуются самые примитивные компоненты, но мы не пропускаемimportчтобы ввести его на страницу. Хорошо, давайте просто напишем этот компонент vue с изображением всплывающего уведомления в начале (то же самое для сообщения и предупреждения). Вот непосредственно код, ведь его структура настолько проста, что не является предметом рассмотрения в этой главе:
<!-- main.vue -->
<template>
<div class="toast">
<p>服务器错误,请稍后重试</p>
</div>
</template>
<script>
export default {
name: "Toast",
mounted() {
setTimeout(() => {
// 3s 后通过父级移除子元素的方式来移除该组件实例和 DOM 节点
this.$destroy(true);
this.$el.parentNode.removeChild(this.$el);
}, 3000);
}
};
</script>
<style lang="scss" scoped>
.toast {
display: flex;
align-items: center;
justify-content: center;
position: fixed;
top: 0;
bottom: 0;
left: 0;
right: 0;
color: #fff;
z-index: 9999;
background: transparent;
> p {
padding: 12px 22px;
font-size: 18px;
border-radius: 4px;
background: rgba(17, 17, 17, 0.7);
}
}
</style>
Приведенный выше контент должен быть понятен каждому, поэтому я прямо расскажу о следующих ключевых моментах.
Напишите main.js
Мы создаем новый файл main.js в том же каталоге, что и main.vue. Взглянем на содержимое файла (не много, это уже минимальная версия)👇:
// main.js
import Vue from "vue"; // 引入 Vue 是因为要用到 Vue.extend() 这个方法
import Main from "./main.vue"; // 引入刚才的 toast 组件
let ToastConstructor = Vue.extend(Main); // 这个在前面的前置知识内容里面有讲到
let instance;
const Toast = function() {
instance = new ToastConstructor().$mount(); // 渲染组件
document.body.appendChild(instance.$el); // 挂载到 body 下
};
export default Toast;
Приведенный выше код предоставляет функцию Toast. Зачем выставлять функцию? Причина проста: вы думаете, неужели мы, в конце концов, собираемсяthis.$toast()Чтобы вызвать компонент, грубо говоря, вызов через js по сути является вызовом функции. то естьthis.$toast()заключается в выполнении экспорта в приведенном выше кодеexport default Toast, то есть выполняется функция Toast (const Toast = function() {}), поэтому, когда мы вызываемthis.$toast()когда он действительно выполняетсяToast()функция. а такжеToast()Функция делает только одно: монтирует компонент под корпус вручную.
Добавлю 🤐: Вообще наш общий$mount("#app"), то есть смонтировать компонент в#appпод,<router-view />также включены в#app, но наше всплывающее уведомление помещается вbodyниже, то есть не подлежит#appа также<router-view />Поэтому, когда мы переключаем страницы (роутинг), этот компонент тоста не исчезнет сразу, так что обратите на это внимание 😯.
Кстати, вот структура каталогов компонента, как показано на следующем рисунке:
начать звонить
Метод вызова очень прост.Во-первых, мы добавляем две строки кода в файл ввода main.js(это не то же самое, что выше😢), чтобы мы могли вызывать его напрямую с помощью js там, где это необходимо, как показано на следующем фигура:Затем протестируйте его на странице, например:
Запустите код:
Ну, это довольно хорошо, немного завершенное чувство 👏👏👏.
Поддержка передаваемых параметров
Не волнуйтесь, мы, кажется, не хватаем чего-то 🤔. . . Кстати, это еще не поддерживает передачу параметров, назови это напрямуюthis.$toast()Он может показывать только ---- ошибку сервера, попробуйте еще раз позже (это все бэкэнд-пот 😊). Но мы амбициозный фронтенд и этим ограничиваться не можем, поэтому сейчас попробуем добавить следующие два настраиваемых параметра, вот беремdurationа такжеcontentВозьмите каштан 🌰.
Во-первых, нам нужно изменить содержимое компонента main.vue (на самом деле серьезных изменений нет), как показано ниже:
<!-- main.vue 可配置版 -->
<template>
<div class="toast">
<p>{{ content }}</p>
</div>
</template>
<script>
// 主要就改了 data
export default {
name: "Toast",
data() {
return {
content: "",
duration: 3000
};
},
mounted() {
setTimeout(() => {
this.$destroy(true);
this.$el.parentNode.removeChild(this.$el);
}, this.duration);
}
};
</script>
Приведенный выше код должен быть понятен, а теперь давайте посмотрим, что изменилось в main.js:
// main.js 可配置版
import Vue from "vue";
import Main from "./main.vue";
let ToastConstructor = Vue.extend(Main);
let instance;
const Toast = function(options = {}) { // 就改了这里,加了个 options 参数
instance = new ToastConstructor({
data: options // 这里的 data 会传到 main.vue 组件中的 data 中,当然也可以写在 props 里
});
document.body.appendChild(instance.$mount().$el);
};
export default Toast;
На самом деле main.js почти не изменился, просто добавили параметр в функцию. Быть осторожнымnew ToastConstructor({ data: options })Данные в нем — это данные в компоненте main.vue, а не имя поля, которое взято невзначай, входящийoptionsБудет объединен с данными в компоненте (Credit to Vue).
Эм. . . Да, это так просто, теперь давайте назовем это:
<script>
export default {
methods: {
showToast() {
this.$toast({
content: "哈哈哈哈,消失的贼快",
duration: 500
});
}
}
};
</script>
Запустите его, чтобы увидеть:Конечно, это еще не конец, мы продолжаем добавлять небольшую особенность 🙄. . .
Поддержите это.$toast.error()
Здесь мы намерены поддержатьthis.$toast.error()а такжеthis.$toast.success()Эти два метода, поэтому наш первый шаг — изменить содержимое файла main.vue (в основном на основеtypeзначение для изменения стиля компонента), например:
<!--main.vue-->
<template>
<div class="toast" :class="type ? `toast--${type}` : ''">
<p>{{ content }}</p>
</div>
</template>
<script>
export default {
...
data() {
return {
type: "",
content: "",
duration: 3000
};
},
...
};
</script>
<style lang="scss" scoped>
.toast {
...
&--error p { background: rgba(255, 0, 0, 0.5); }
&--success p { background: rgba(0, 255, 0, 0.5); }
}
</style>
Второй,this.$toast.error()На самом деле, это эквивалентноToast.error(), поэтому наша цель сейчас — расширить метод до функции Toast, что относительно просто. Давайте сначала посмотрим на код, а затем объясним его:
// main.js
const Toast = function(options = {}) {
...
};
// 以下就是在 Toast 函数中拓展 ["success", "error"] 这两个方法
["success", "error"].forEach(type => {
Toast[type] = options => {
options.type = type;
return Toast(options);
};
});
export default Toast;
Мы видим, чтоToast.error()а такжеToast.success()наконец позвониToast(options)Эта функция, но перед ее вызовом необходимо выполнить еще одну обработку, то есть["success", "error"]какtypeпараметры объединены вoptionsВнутрь и потом пройти, вот и все 😬.
Затем попробуйте эффект:
<script>
export default {
methods: {
showToast() {
this.$toast({ content: "这是正常的" });
},
showErrorToast() {
this.$toast.error({ content: "竟然失败了" });
},
showSuccessToast() {
this.$toast.success({ content: "居然成功了" });
}
}
};
</script>
Великая похвала, великая. отличный. . без. . . Синьцзян. . . . . 👍
Эпилог
Пока что сделан простенький тост-компонент, вызываемый через js, всего несколько строчек кода — это еще тест на js-навыки 💪. Конечно, это всего лишь сверхпростая версия демо, которая явно не идеальна и надежна, поэтому мы можем расширить на этой основе, например, когдаduration <= 0, мы оставляем всплывающее уведомление отображаемым, а затем разворачиваемcloseметод закрытия и так далее. Но опять же, как гласит старая поговорка, практика — единственный критерий истины. На бумаге в конце концов я чувствую себя мелким, и я абсолютно точно знаю, что это дело должно быть сделано. шаг за шагом, день день вверх! 🎉 🎉 🎉
Наконец, в конце, вот две статьи, которые полезны для этой статьи:
1. Исходный код компонента исходного элемента все еще можно увидеть таким образом.
2. Создайте свою собственную библиотеку пользовательского интерфейса на основе vue-cli3.