Описание Проекта
vue + axios + vue-router + vuex + ElementUI
vue
обновление данных vue, просмотр, а не обновление
Свойства, которые существуют в данных только при создании экземпляра, являются реактивными, Vue не может обнаружить добавление или удаление свойств объекта;
Реактивные свойства могут быть добавлены к вложенным объектам с помощью метода Vue.set(object, key, value)
Vue.set(vm.userProfile, 'age', 27)
this.$set(this.transportAddData.serviceOrderList[a].serviceOrderItems[i], 'deletePoundIds', [])
vue данные и методы
соображения об обнаружении изменений объекта vue
Vue не может обнаружить следующие изменяющиеся массивы:
- Когда вы устанавливаете элемент напрямую с помощью индекса, например: vm.items[indexOfItem] = newValue
- При изменении длины массива, например: vm.items.length = newLength
Оптимизация непрерывных триггерных событий
Непрерывный запуск события может использовать регулирование функции и защиту от сотрясений для оптимизации производительности.
//防抖
function(){
...
clearTimeout(timeoutId);
timeoutId = setTimeout(function () {
console.log('content', content);
player(content.msgTypeId, comId)
}, 500);
...
}
// 节流
var canRun = true;
document.getElementById("throttle").onscroll = function(){
if(!canRun){
// 判断是否已空闲,如果在执行中,则直接return
return;
}
canRun = false;
setTimeout(function(){
console.log("函数节流");
canRun = true;
}, 300);
};
Throttling (дросселирование) и Debouncing (анти-тряска) javaScript
nextTick
Выполняет отложенный обратный вызов после завершения следующего цикла обновления DOM. Используйте этот метод сразу после изменения данных, чтобы получить обновленную модель DOM.
get() {
this.$http.get('/api/article').then(function (res) {
this.list = res.data.data.list
// ref list 引用了ul元素,我想把第一个li颜色变为红色
document.querySelectorAll('li')[0].style.color = 'red' //这里会报错-,因为还没有 li
this.$nextTick( ()=> {
document.querySelectorAll('li')[0].style.color = 'red'
})
})
},
Ошибка автовоспроизведения аудиофайла
Google Chrome (Chrome 66) ошибка автовоспроизведения звука
DOMException: play() failed because the user didn’t interact with the document first.
Решение: АудиоКонтекст
// Chrome
request.get('/baseConfig/messageAudio/play', {
params: {
"comId": Cookies.get('comId'),
"msgTypeId": id
},
responseType: 'arraybuffer' // 这里需要设置xhr response的格式为arraybuffer
})
.then(req => {
...
let context = new (window.AudioContext || window.webkitAudioContext)();
context.decodeAudioData(req.data, decode => play(context, decode));
function play (context, decodeBuffer) {
sourceadio = context.createBufferSource();
sourceadio.buffer = decodeBuffer;
sourceadio.connect(context.destination);
// 从0s开始播放
sourceadio.start(0);
}
...
})
Chrome 66 отключает звук после автозапуска
AudioContext
AudioContext.decodeAudioData()
vuex
Способ и разница с использованием Vuex для изменения состояния
- Вы можете напрямую использовать это. $ Store.state.Variable = xxx;
- this.
store.commit(commitType, payload)
Та же самая точка: может изменять переменные в состоянии и реагировать (может запускать обновления представления)
Разница: если strict: true передается, когда Vue создает хранилище, включается строгий режим, то любая операция, которая изменяет состояние, пока она не проходит
функция мутации, vue сообщит о следующей ошибке
throw error : [vuex] Do not mutate vuex store state outside mutation handlers。
Преимущества использования фиксации для отправки на мутацию для изменения состояния: vuex может записывать каждую запись об изменении состояния, сохранять моментальные снимки состояния и реализовывать такие операции, как перемещение по времени/откат.
Разница между отправкой и фиксацией заключается в следующем:
Использование отправки — это асинхронная операция, фиксация — синхронная операция,
Поэтому в целом рекомендуется использовать фиксацию напрямую, то есть this.$store.commit(commitType, payload), чтобы предотвратить проблемы с задержкой, вызванные асинхронными операциями.
что такое векс
const store = new Vuex.Store({
state: {
count: 0
},
mutations: {
increment (state) {
state.count++
}
},
actions: {
increment (context) {
context.commit('increment')
}
}
})
== Состояние в vuex по сути является скрытым компонентом vue без шаблона. ==
axios
Проблемы совместимости
Почтовый запрос Edge 41.16299.15.0 будет автоматически преобразован для получения
microsoft-edge/platform/issues
Vue использует axios для отправки запросов в браузерах EDGE в запросы на получение.
отменить запрос
Сценарий: Токен добавляется в перехватчик для каждого запроса, и фон определяет, истек ли срок действия токена, при входе на страницу срабатывает несколько запросов, а срок действия токена истек. В это время необходимо знать, что срок действия токена истек после завершения первого запроса, и появится всплывающее окно, и страница перейдет к запросу после входа в систему и остановки; в противном случае будет несколько всплывающих окон. подсказки из-за множественных запросов и перехвата ответов axios.
- решение
axios имеет собственный метод отмены cancelToken, а затем останавливает предыдущий запрос после скачка маршрутизации
// 请求拦截中 添加 cancelToken
axios.interceptors.request.use(config => {
config.cancelToken = store.source.token
return config
}, err => {
return Promise.reject(err)
})
// 路由跳转中进行判断
router.beforeEach((to, from, next) => {
const CancelToken = axios.CancelToken
store.source.cancel && store.source.cancel()
store.source = CancelToken.source()
next()
})
//sort文件/
state: {
source: {
token: null,
cancel: null
}
}
axios api
Используйте axios для отмены всех запросов при изменении маршрута
Перехватчик запроса Axios и отмена функции ожидающего запроса в проекте vue
Существует проблема: если всплывающее окно с запросом на истечение срока действия токена является вторым всплывающим окном подтверждения, и переход на страницу будет выполнен после повторного подтверждения, то предыдущий запрос на странице будет продолжен до нажатия кнопки «Подтвердить»;
Решение. Добавьте глобальное состояние во всплывающее окно и определите, нужно ли раскрывать всплывающее окно в соответствии с состоянием.
предварительный запрос
Перекрестный домен CORS
CORS требует поддержки как браузера, так и сервера. В настоящее время все браузеры поддерживают эту функцию, == Браузер IE не может быть ниже IE10. ==
Браузеры делят запросы CORS на две категории: простые запросы и не очень простые запросы.
- простой запрос
- Метод запроса является одним из трех методов:
HEAD
GET
POST - Информация заголовка HTTP не превышает следующих полей:
Принимать
Accept-Language
Content-Language
Last-Event-ID
Content-Type: ограничено тремя значениями application/x-www-form-urlencoded, multipart/form-data, text/plain
Простые запросы не запускают предварительные запросы CORS.
- не простой запрос
Запрос является непростым запросом, если он соответствует любому из следующих условий:
- Был использован любой из следующих методов HTTP:
PUT
DELETE
CONNECT
OPTIONS
TRACE
PATCH - Искусственно задайте другие поля заголовка, отличные от поля заголовка CORS-safe. Коллекция: Принимать Accept-Language Язык содержания Content-Type (но обратите внимание на дополнительные требования ниже) ДНР Нисходящая линия Сохранить данные Viewport-Ширина Ширина
- Значение Content-Type не является одним из следующих:
application/x-www-form-urlencoded
multipart/form-data
text/plain - Объект XMLHttpRequestUpload в запросе имеет любое количество зарегистрированных прослушивателей событий.
- В запросе использовался объект ReadableStream.
- предварительный запрос
Для непростых запросов запрос запроса, инициированный методом HTTP OPTIONS, будет добавлен перед формальным общением, которое называется предварительным запросом. чтобы узнать, разрешает ли сервер фактический запрос.
Использование «предварительного запроса» может предотвратить неожиданное влияние междоменных запросов на пользовательские данные сервера.
==Этот метод не повлияет на ресурсы сервера==
- Оптимизация
Access-Control-Max-Age: <delta-seconds> //单位是秒。
Указывает, как долго может кэшироваться возвращаемый результат предварительного запроса (то есть информация, предоставленная методами Access-Control-Allow-Methods и Access-Control-Allow-Headers).
Vue Router
Разница между push и replace
push добавит новую запись в историю, а replace просто заменит исходную запись без добавления новой записи; Это приводит к тому, что страница, пропущенная методом замены, не может вернуться на предыдущую страницу (аналогично window.history).
Отложенная загрузка маршрута
Чтобы повысить скорость загрузки страницы и реализовать загрузку по требованию, то есть соответствующие компоненты загружаются при доступе к маршруту, мы можем объединить асинхронные компоненты vue и функцию разделения кода веб-пакета для реализации ленивой загрузки маршруты.
{
path: '/iov/login',
name: '登录',
component: resolve => require(['@/views/login/login'], resolve),
},
{
path:'/iov/organization',
name:'组织管理',
component:() => import('@/views/enterprise/organization')
}
Отложенная загрузка маршрутизации Vue Router
vue асинхронный компонент
vue + vue-router lazy load import/require+require
elementUI
Во всплывающем окне формы elementform очищает остаточный запрос проверки
Добавьте другую ссылку (REFNAME) в форму, если есть такая же ссылка, это приведет к тому, что запрос остаточного подтверждения не будет очищен.
this.dialogTranspor = true
//弹窗打开后 dom 没有生成,所有要用 this.$nextTick
this.$nextTick(function () {
this.$refs.REFNAME.resetFields();
})
Количество страниц не может отображаться правильно
Сценарий: страница списка возвращается на страницу списка после перехода к сведениям или другим страницам, соответствующий номер страницы не может отображаться нормально (номер страницы помещается в состояние), но запрошенные данные в норме;
Решение: Количество страниц и общее количество страниц должны быть в одном объекте, иначе текущее количество страниц не может нормально отображаться
data() {
return {
//完成查询条件
searchComplate: {
"comId": Cookies.get('comId'),
"transportOrderCode": null,
"orderCode": null,
"customerId": null,
"abnormal": 2,
"startTime": null,
"endTime": null,
"pageNum": 1,
"pageSize": 20,
total: 0,
currentRow: '',
dataArea: ['', ''],
activeName: '',
expands: []
},
}
}
Динамическая многоуровневая проверка формы
<li v-for="(item,index) in transportAddData.serviceOrderList">
<template v-for="(subItem,subIndex) in item.serviceOrderItems">
<tr >
<td>
<el-form-item :prop="'serviceOrderList.'+index+'.serviceOrderItems.' + subIndex + '.addressName'"
:rules="{required: true, message: '卸货地不能为空', trigger: 'blur'}">
<el-input v-model="subItem.addressName" placeholder="地址"></el-input>
</el-form-item>
</td>
<td>
<el-form-item :prop="'serviceOrderList.'+index+'.serviceOrderItems.' + subIndex + '.planTonnage'"
:rules="[{required: true, message: '必填项', trigger: 'blur'},{pattern: /^((([1-9]+(\d+)?)(\.\d+)?)|(0\.\d+))$/, message: '必须为正数且不为0'}]">
<el-input v-model="subItem.planTonnage"
placeholder="预卸吨数"></el-input>
</el-form-item>
</td>
...
</tr>
</template>
</li>