layout
Vuex централизованно управляет состоянием
Статус боковой панели, будь то мобильный терминал, плавающий заголовок, отображать ли метку, отображать ли настройки
Рендеринг разных классов в зависимости от состояния
Адаптация мобильного терминала
Измените размер страницы мониторинга, чтобы определить, является ли это мобильным бизнесом, отделите ее и используйте метод миксина.
Различать внутренние маршруты и внешние ссылки
динамические компонентыv-bind
Уникальный метод письма
<component :is="type" v-bind="linkProps(to)">
<slot />
</component>
methods: {
linkProps(to) {
if (this.isExternal) {
return {
href: to,
target: '_blank',
rel: 'noopener'
}
}
return {
to: to
}
}
}
Вкладка История
1. Горизонтальную полосу прокрутки можно прокручивать колесиком мыши.
2. Всплывающее меню правой кнопкой мыши.
3. Полоса прокрутки может прокручиваться до определенной позиции
Обработка горизонтальной полосы прокрутки
компонент панели прокрутки, прослушивающий события колесика мыши,
<el-scrollbar ref="scrollContainer" :vertical="false" class="scroll-container" @wheel.native.prevent="handleScroll">
<slot />
</el-scrollbar>
Изменить горизонтальное смещение полосы прокрутки
handleScroll(e) {
const eventDelta = e.wheelDelta || -e.deltaY * 40
const $scrollWrapper = this.scrollWrapper
$scrollWrapper.scrollLeft = $scrollWrapper.scrollLeft + eventDelta / 4
}
контекстное меню
прокрутить до указанной позиции
Манипулировать домом без jquery
const refs.scrollContainer.containerWidth = $container.offsetWidth
moveToTarget(currentTag) {
const $container = this.$refs.scrollContainer.$el
const $containerWidth = $container.offsetWidth
const $scrollWrapper = this.scrollWrapper
const tagList = this.$parent.$refs.tag
let firstTag = null
let lastTag = null
// find first tag and last tag
if (tagList.length > 0) {
firstTag = tagList[0]
lastTag = tagList[tagList.length - 1]
}
if (firstTag === currentTag) {
$scrollWrapper.scrollLeft = 0
} else if (lastTag === currentTag) {
$scrollWrapper.scrollLeft = $scrollWrapper.scrollWidth - $containerWidth
} else {
// find preTag and nextTag
const currentIndex = tagList.findIndex(item => item === currentTag)
const prevTag = tagList[currentIndex - 1]
const nextTag = tagList[currentIndex + 1]
// the tag's offsetLeft after of nextTag
const afterNextTagOffsetLeft = nextTag.$el.offsetLeft + nextTag.$el.offsetWidth + tagAndTagSpacing
// the tag's offsetLeft before of prevTag
const beforePrevTagOffsetLeft = prevTag.$el.offsetLeft - tagAndTagSpacing
if (afterNextTagOffsetLeft > $scrollWrapper.scrollLeft + $containerWidth) {
$scrollWrapper.scrollLeft = afterNextTagOffsetLeft - $containerWidth
} else if (beforePrevTagOffsetLeft < $scrollWrapper.scrollLeft) {
$scrollWrapper.scrollLeft = beforePrevTagOffsetLeft
}
}
}
RgihtPanel
установлен на корпусе
insertToBody() {
const elx = this.$refs.rightPanel
// 或是 const elx = this.$
const body = document.querySelector('body')
body.insertBefore(elx, body.firstChild)
}
Метод создания пакета
import Vue from 'vue'
function create(Component, props) {
const vm = new Vue({
render(h) {
return h(Component, {props})
}
}).$mount();
document.body.appendChild(vm.$el);
const comp = vm.$children[0];
comp.remove = () => {
document.body.removeChild(vm.$el);
vm.$destroy();
}
return comp;
}
export default create;
Нажмите на формулировку слоя маски, чтобы закрыть
evt.target.closest определяет, является ли область, по которой щелкнули, маской
closeSidebar(evt) {
const parent = evt.target.closest('.rightPanel')
if (!parent) {
this.show = false
window.removeEventListener('click', this.closeSidebar)
Анимация перехода при переключении маршрута
<template>
<section class="app-main">
<transition name="fade-transform" mode="out-in">
<keep-alive :include="cachedViews">
<router-view :key="key" />
</keep-alive>
</transition>
</section>
</template>
/* fade-transform */
.fade-transform-leave-active,
.fade-transform-enter-active {
transition: all .5s;
}
.fade-transform-enter {
opacity: 0;
transform: translateX(-30px);
}
.fade-transform-leave-to {
opacity: 0;
transform: translateX(30px);
}
индикатор выполнения страницы
import NProgress from 'nprogress'; // progress bar
import 'nprogress/nprogress.css'; // progress bar style
NProgress.configure({ showSpinner: false }); // NProgress Configuration
router.beforeEach((to, from, next) => {
// token start
NProgress.start();
next();
NProgress.done();
});
разрешения на уровне кнопок
Пользовательская директива v-permission
Логика: Передаем разрешение кнопки, получаем разрешение текущего пользователя, определяем есть ли разрешение пользователя в разрешении кнопки, если нет, значит разрешения нет, удаляем DOM кнопки.
верх
плавная прокрутка
Исходный код не прост для понимания, и с помощью Interval я сам его оптимизировал, и принял метод сглаживания кадра анимации к верху
backToTop() {
if (this.isMoving) return
const scrollTop = window.pageYOffset
if (scrollTop > this.backPosition) {
window.requestAnimationFrame(this.backToTop)
window.scrollTo(0, scrollTop - scrollTop / 20)
}
}
библиотека иконок svg
- Зарегистрируйте компонент диаграммы svg глобально
- Автоматически импортировать ресурсы SVG
require.context('./svg', false, /\.svg$/)
Динамически загружать скрипты
Редактор уценки
плагин tui-editor
Элемент конфигурации отдельного управления js
Sticky
Прислушайтесь к прокрутке и используйте API getBoundingClientRect(), чтобы получить размер элемента и его положение относительно области просмотра.
Когда высота меньше, чем переданный stickyTop, установите фиксированную позицию элемента.
handleScroll() {
const width = this.$el.getBoundingClientRect().width
this.width = width || 'auto'
const offsetTop = this.$el.getBoundingClientRect().top
if (offsetTop < this.stickyTop) {
this.sticky()
return
}
this.handleReset()
},
sticky() {
if (this.active) {
return
}
this.position = 'fixed'
this.active = true
this.width = this.width + 'px'
this.isSticky = true
},
кнопка эффект волны воды
Создать директиву v-waves
При щелчке элемента в элементе создается круговой абсолютный диапазон, размер зависит от ширины элемента, по которому щелкнули, положение зависит от положения щелчка мыши, плюс анимация непрозрачности и масштаба.
Примечание. Мониторинг и отвязка событий кликов
.....
if (!el[context]) {
el[context] = {
removeHandle: handle
}
} else {
el[context].removeHandle = handle
}
return handle
}
export default {
bind(el, binding) {
el.addEventListener('click', handleClick(el, binding), false)
},
update(el, binding) {
el.removeEventListener('click', el[context].removeHandle, false)
el.addEventListener('click', handleClick(el, binding), false)
},
unbind(el) {
el.removeEventListener('click', el[context].removeHandle, false)
el[context] = null
delete el[context]
}
}
Диаграмма
resize mixin
Поместите в миксин монитор обработки ресайза вьюпорта, обратите внимание на отвязку события ресайза
лист
Фильтр записи
<el-table-column label="Status" class-name="status-col" width="100">
<template slot-scope="{row}">
<el-tag :type="row.status | statusFilter">
{{ row.status }}
</el-tag>
</template>
</el-table-column>
filters: {
statusFilter(status) {
const statusMap = {
published: 'success',
draft: 'info',
deleted: 'danger'
}
return statusMap[status]
},
typeFilter(type) {
return calendarTypeKeyValue[type]
}
},