10 избранных вопросов для интервью
1. Как реализовать V-модель Vue, каков фактический синтаксис?
Компания: Маймай
Категория: Вью
1. Синтаксический сахар
Относится к грамматике, добавленной к компьютерному языку, которая не влияет на функцию языка, но более удобна для использования программистами. Вообще говоря, использование синтаксического сахара может повысить читабельность программы, тем самым уменьшив вероятность ошибки в программном коде. Sugar достигает эквивалентности во время выполнения без изменения синтаксической структуры, в которую он помещен. Можно просто понять, что скомпилированный код после добавления сахара такой же, как и до добавления сахара, код более лаконичный и гладкий, код более семантически естественный.
Во-вторых, принцип реализации
1. Действие на общие элементы формы
динамически связанныйinput из valueуказал наmessgaeпеременная и запускinputКогда событие переходит в динамикуmessageустановить целевое значение
<input v-model="sth" />
// 等同于
<input
v-bind:value="message"
v-on:input="message=$event.target.value"
>
//$event 指代当前触发的事件对象;
//$event.target 指代当前触发的事件对象的dom;
//$event.target.value 就是当前dom的value值;
//在@input方法中,value => sth;
//在:value中,sth => value;
2. Воздействовать на компонент
В пользовательских компонентах v-model по умолчанию использует свойство с именем value и событие с именем input.
По сути, синтаксический сахар для связи между родительскими и дочерними компонентами, реализованный через prop и $.emit.
поэтому родительский компонентv-modelСинтаксический сахар может быть существенно изменен для'<child :value="message" @input="function(e){message = e}"></child>'
В реализации компонента мы можем передатьсвойство v-моделиЧтобы настроить имя свойства, полученное дочерним компонентом, и имя отправленного события.
пример
// 父组件
<aa-input v-model="aa"></aa-input>
// 等价于
<aa-input v-bind:value="aa" v-on:input="aa=$event.target.value"></aa-input>
// 子组件:
<input v-bind:value="aa" v-on:input="onmessage"></aa-input>
props:{value:aa,}
methods:{
onmessage(e){
$emit('input',e.target.value)
}
}
По умолчанию v-модель компонента будет использовать значение в качестве реквизита и ввод в качестве события.
Но некоторые типы ввода, такие как переключатели и кнопки-флажки, могут захотеть использовать свойство value для разных целей. Конфликтов, возникающих из этих ситуаций, можно избежать, используя вариант модели.
js отслеживает изменение входных данных в поле ввода, с oninput это событие будет срабатывать сразу после изменения данных.
Данные $emit отправляются через событие ввода и принимаются в родительском компоненте.
Родительский компонент устанавливает значение v-model в значение из input$emit.
2. Что происходит после setState в React? Почему setState по умолчанию асинхронный? Когда setState синхронен?
Компания: WeDoctor
Категория: Реагировать
1. Что происходит после setState в React
После вызова в коде функции setState React объединит входящий объект параметра с текущим состоянием компонента, после чего запустит так называемый процесс согласования (Reconciliation).
После процесса согласования React строит дерево элементов React на основе нового состояния и приступает к повторному рендерингу всего пользовательского интерфейса относительно эффективным способом.
После того, как React получит дерево элементов, React автоматически вычислит разницу узлов между новым деревом и старым деревом, а затем минимизирует и повторно визуализирует интерфейс в соответствии с разницей.
В алгоритме расчета разницы React может с относительной точностью узнать, что изменилось и как должно было измениться, что гарантирует обновления по запросу, а не полный повторный рендеринг.
2. Почему setState по умолчанию асинхронный
Если все setState синхронны, это означает, что каждый раз, когда setState выполняется (возможно, в синхронном коде, несколько setStates), снова модифицируется vnode diff+dom, что крайне плохо сказывается на производительности. Если он асинхронный, вы можете объединить несколько setStates в синхронном коде в обновление компонента.
3. Когда setState синхронен
В setTimeout или собственных событиях setState является синхронным.
3. Несколько вкладок соответствуют только одному блоку содержимого. Щелчок по каждой вкладке будет запрашивать интерфейс и отображать его в поле содержимого. Как убедиться, что вкладки часто нажимаются, но данные могут отображаться нормально?
Компания: Айфанер
Категория: JavaScript
1. Анализ
Поскольку время обработки каждого запроса несовместимо, это может привести к тому, что сначала будет отправлен запрос, а затем ответ, то есть последовательность ответа на запрос и последовательность отправки запроса будут несогласованными, что приведет к неправильному отображению данных.
То есть это можно понимать как непрерывный запуск нескольких запросов, как гарантировать, что последовательность ответа на запрос соответствует последовательности отправки запроса. В проблемном сценарии пользователя заботит только правильность отображения последних данных, что можно упростить следующим образом: непрерывная активация нескольких запросов, как убедиться, что результатом последнего ответа является последний отправленный запрос (не важно, предыдущий запрос был отправлен или ответ был успешным)
Похожие сценарии: мгновенный поиск в поле ввода, быстрое переключение номеров страниц в форме
2. Решения
Anti-shake (отфильтровать некоторые ненужные запросы) + отменить последний невыполненный запрос (гарантировать порядок ответа последнего запроса)
Способ отмены запроса:
-
XMLHttpRequestиспользоватьabortapiотменить запрос -
axiosиспользоватьcancel tokenотменить запрос
Псевдокод (имитация запроса с помощью setTimeout, отмена запроса с помощью clearTimeout)
/**
* 函数防抖,一定时间内连续触发事件只执行一次
* @param {*} func 需要防抖的函数
* @param {*} delay 防抖延迟
* @param {*} immediate 是否立即执行,为true表示连续触发时立即执行,即执行第一次,为false表示连续触发后delay ms后执行一次
*/
let debounce = function(func, delay = 100, immediate = false) {
let timeoutId, last, context, args, result
function later() {
const interval = Date.now() - last
if (interval < delay && interval >= 0) {
timeoutId = setTimeout(later, delay - interval)
} else {
timeoutId = null
if (!immediate) {
result = func.apply(context, args)
context = args = null
}
}
}
return function() {
context = this
args = arguments
last = Date.now()
if (immediate && !timeoutId) {
result = func.apply(context, args)
context = args = null // 解除引用
}
if (!timeoutId) {
timeoutId = setTimeout(later, delay)
}
return result
}
}
let flag = false // 标志位,表示当前是否正在请求数据
let xhr = null
let request = (i) => {
if (flag) {
clearTimeout(xhr)
console.log(`取消第${i - 1}次请求`)
}
flag = true
console.log(`开始第${i}次请求`)
xhr = setTimeout(() => {
console.log(`请求${i}响应成功`)
flag = false
}, Math.random() * 200)
}
let fetchData = debounce(request, 50) // 防抖
// 模拟连续触发的请求
let count = 1
let getData = () => {
setTimeout(() => {
fetchData(count)
count++
if (count < 11) {
getData()
}
}, Math.random() * 200)
}
getData()
/* 某次测试输出:
开始第2次请求
请求2响应成功
开始第3次请求
取消第3次请求
开始第4次请求
请求4响应成功
开始第5次请求
请求5响应成功
开始第8次请求
取消第8次请求
开始第9次请求
请求9响应成功
开始第10次请求
请求10响应成功
*/
Предупреждение высокой энергии впереди 🚨 🚨 🚨
Поскольку статья слишком длинная и влияет на впечатления от чтения, ответы на следующие 7 вопросов будут свернуты, нажмитеПосмотреть анализ, вы можете просмотреть все ответы, выберите интересующий вас вопрос, чтобы просмотреть ответ~
4. Понимание виртуального DOM? Что в основном делает виртуальный DOM? Что такое виртуальный DOM?
Компания: Youzan, WeDoctor, 58 лет
Категория: Реагировать, Vue
Посмотреть анализ
1. Что такое виртуальный дом
По сути, виртуальный дом — это объект JavaScript, который представляет структуру DOM в виде объектов. Состояние страницы абстрагируется в виде объектов JS, и с помощью различных инструментов рендеринга возможен кросс-платформенный рендеринг. Благодаря механизму обработки транзакций результаты нескольких модификаций DOM одновременно обновляются на странице, тем самымЭффективно сократите количество отрисовок страниц, уменьшите количество перерисовок и переупорядочений, которые изменяют DOM, и улучшите производительность отрисовки..
Виртуальный DOM — это абстракция DOM, а этот объект — более легкое описание DOM. Первоначальная цель его дизайна — сделать его более кроссплатформенным. Например, Node.js не имеет DOM. Если вы хотите реализовать SSR, то один из способов — использовать виртуальный дом, потому что виртуальный дом сам по себе является объектом js.
Прежде чем код будет отображен на странице, vue или react преобразуют код в объект (виртуальный DOM). Реальная структура DOM описывается в виде объектов и, наконец, отображается на странице. Перед каждым изменением данных виртуальный DOM будет кэшироваться, при изменении данных текущий виртуальный DOM будет сравниваться с кешированным виртуальным DOM.
Алгоритм diff инкапсулирован в vue or react.Этот алгоритм используется для сравнения и модификации изменений во время рендеринга.Исходные данные рендерятся без каких-либо изменений.
Кроме того, базовым требованием современных интерфейсных фреймворков является отсутствие необходимости вручную манипулировать DOM.С одной стороны, ручное манипулирование DOM не может гарантировать производительность программы.Если проверка не является строгой в многопользовательской совместный проект, некоторые разработчики могут писать низкопроизводительный код, но, с другой стороны, более важно, что отказ от ручных манипуляций с DOM может значительно повысить эффективность разработки.
2. Зачем использовать виртуальный DOM
1. Гарантированная нижняя граница производительности, обеспечивающая достойную производительность без ручной оптимизации.
Взгляните на процесс рендеринга страницы:
- Разобрать HTNL ☞ Генерировать DOM🌲 ☞ Генерировать CSSOM ☞ Макет ☞ Рисовать ☞ Компилятор
Давайте сравним процесс работы реального DOM и Virtual DOM при модификации DOM и посмотрим на потребление производительности их перестановкой и перерисовкой:
- Реальный DOM: сгенерировать строку HTML + перестроить все элементы DOM
- Виртуальный DOM: Генерация vNode + DOMDiff + необходимые обновления dom
Подготовка виртуального DOM для обновления DOM занимает больше времени, то есть на уровне JS, и его потребление чрезвычайно дешево по сравнению с большим количеством операций с DOM. You Yuxi сказал на форуме сообщества:Гарантия, которую дает фреймворк, заключается в том, что я могу обеспечить достойную производительность без необходимости ручной оптимизации.
2. Кроссплатформенность
Виртуальный DOM — это, по сути, объект JavaScript, которым можно легко управлять на разных платформах, таких как рендеринг на стороне сервера, uniapp и т. д.
3. Действительно ли виртуальный DOM лучше производительности реального DOM?
- При первом рендеринге большого количества DOM это будет медленнее, чем вставка innerHTML из-за дополнительного уровня вычисления виртуального DOM.
- Точно так же, как это может гарантировать более низкий предел производительности, это все еще быстрее, когда целевые оптимизации выполняются во время реальных манипуляций с DOM.
5. Почему Webpack тормозит и как его оптимизировать
Категория: Инжиниринг
Посмотреть анализ
1. Почему вебпак работает медленно?
Webpack — это так называемый сборщик модулей, внутри которого есть циклические ссылки для анализа зависимостей между модулями, парсинга файлов в AST, их обработки через ряд различных загрузчиков и, наконец, упаковки их всех в один js-файл.
До webpack4 методов оптимизации скорости упаковки было немного, большая часть медленного времени компиляции уходила на компиляцию разных загрузчиков, после webpack4 он впитал в себя идеи многих отличных инструментов.
Такие как поддержка конфигурации 0, многопоточность и другие функции, скорость также значительно улучшена, но все еще есть некоторые методы оптимизации. Например, разумное разделение кода, извлечение общего кода, извлечение ресурсов CSS.
2. Оптимизируйте скорость сборки Webpack
- Используйте более высокую версию Webpack (используя webpack4)
- Многопоточная/многоэкземплярная конструкция: HappyPack (не поддерживается), загрузчик потоков
- Усадочная область упаковки:
-
exclude/include(определить область действия правила загрузчика) -
resolve.modulesУкажите абсолютный путь к стороннему модулю (уменьшите ненужные поиски) -
resolve.extensionsМинимизируйте вероятность попыток суффикса -
noParseИгнорировать библиотеки, которые вообще не нужно анализировать (не анализировать, но все равно будут упакованы в пакеты, обратите внимание, что игнорируемые файлы не должны содержать модульные операторы, такие как импорт, требование, определение) - IgnorePlugin (для полного исключения модулей)
- добросовестное использование псевдонимов
-
- Полностью используйте кеш, чтобы улучшить скорость вторичного строительства:
- babel-loader включает кеширование
- terser-webpack-plugin включает кеширование
- Используйте cache-loader или hard-source-webpack-plugin
Примечание. Если загрузчик потоков и загрузчик кеша должны использоваться вместе, сначала поместите загрузчик кеша, затем загрузчик потоков и, наконец, тяжелый загрузчик.
- DLL
- Используйте DllPlugin для подпакета и используйте DllReferencePlugin (ссылка на индекс) для ссылки на manifest.json, чтобы некоторый код, который не изменится, был сначала упакован в статические ресурсы, чтобы избежать повторной компиляции и пустой траты времени.
3. Оптимизация с использованием Webpack4
- Оптимизации, внесенные в V8 (для замен forEach, Map и Set заменяют Object, включают замены indexOf)
- По умолчанию более быстрый алгоритм хеширования MD4
- Webpack AST может быть передан напрямую от загрузчика в AST, что сокращает время анализа
- Используйте строковые методы вместо регулярных выражений
Взгляните на конкретное использование
1.noParse
- Не разрешать зависимости в библиотеке
- Например, библиотека jquery независима, поэтому она не анализирует другие вещи, от которых зависит библиотека.
- Вы можете пользоваться библиотекой во время независимости
module.exports = {
module: {
noParse: /jquery/,
rules:[]
}
}
2.IgnorePlugin
- Игнорировать некоторый контент Не разрешать некоторый контент, на который ссылается зависимая библиотека
- Цитата с момента
./localигнорировать - Если вы хотите использовать локальный, вы должны вручную импортировать его в проект.
import 'moment/locale/zh-cn'
module.exports = {
plugins: [
new Webpack.IgnorePlugin(/\.\/local/, /moment/),
]
}
3.dillPlugin
- Он не будет упакован несколько раз, оптимизируя время упаковки.
- Сначала упакуйте зависимые неизменяемые библиотеки
- Создать файл manifest.json
- Затем введите в webpack.config
-
webpack.DllPlugin,Webpack.DllReferencePlugin
4.happypack -> thread-loader
- Включите многопоточную упаковку для больших проектов
- Есть два аспекта, которые влияют на скорость публикации внешнего интерфейса.Построить, одинкомпрессия, Оптимизация этих двух вещей может значительно сократить время публикации.
5.thread-loader
thread-loaderВаш загрузчик будет работать в рабочем пуле для достижения многопоточных сборок.
Если этот загрузчик размещен перед другими загрузчиками, загрузчик, размещенный после этого загрузчика, будет работать в отдельном пуле рабочих процессов.
// webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.js$/,
include: path.resolve("src"),
use: [
"thread-loader",
// 你的高开销的loader放置在此 (e.g babel-loader)
]
}
]
}
}
Каждый рабочий процесс — это отдельный процесс node.js с ограничением в 600 мс. При этом обмен данными между процессами также будет ограничен. Пожалуйста, используйте его в загрузчике с большими накладными расходами, иначе он не будет работать должным образом.
6. Ускорение сжатия - включить многопоточное сжатие
Не рекомендуется использовать webpack-paralle-uglify-plugin, проект в основном находится в стадии отсутствия сопровождения, вопросами никто не занимается, никакие pr не сливаются.
До Webpack 4.0: uglifyjs-webpack-plugin, параллельный параметр
module.exports = {
optimization: {
minimizer: [
new UglifyJsPlugin({
parallel: true,
}),
],
},};
рекомендуется использовать terser-webpack-plugin
module.exports = {
optimization: {
minimizer: [new TerserPlugin(
parallel: true // 多线程
)],
},
};
6. Сколько существует способов кэширования на стороне клиента? Какова стратегия браузера для отображения с диска и из памяти?
Категория: Сеть и безопасность
Посмотреть анализ
1. Кэш клиента
Политика кэширования браузера:
Каждый раз, когда браузер инициирует запрос, он сначала смотрит в результате и идентификатор кеша в локальном кеше, и судит, следует ли использовать локальный кэш в соответствии с идентификатором кэша. Если кеш является действительным, используйте локальный кеш; в противном случае инициируйте запрос на сервер и несите идентификатор кэша. Процесс кэширования разделен на две части в зависимости от того, должен ли потребоваться запрос HTTP-запроса на сервер:Принудительный кеш и кеш согласования, надежный кеш имеет приоритет над кешем согласования.
Кэширование HTTP начинается со второго запроса
- Когда ресурс запрашивается в первый раз, сервер возвращает ресурс и возвращает стратегию кэширования ресурса в заголовке ответа;
- Во втором запросе браузер оценивает эти параметры запроса, попадает в сильный кеш и напрямую 200, в противном случае он добавляет параметры запроса в заголовок запроса и отправляет его на сервер, чтобы увидеть, попал ли кеш согласования, и возвращает 304, если он попадает, иначе сервер вернет новый ресурс. Вот общая блок-схема работы кэша:
1. Сильный кеш
Сервер уведомляет браузер о времени кеша. В течение времени кеша следующий запрос будет использовать кеш напрямую. Если это не в пределах времени, политика кеша будет сравниваться.
Сильное попадание в кеш напрямую считывает локальные ресурсы браузера, которые отображаются в сети из памяти или с диска
Поля, управляющие принудительным кэшированием: Cache-Control (http1.1) и Expires (http1.0).
- Контроль кэша — это относительное время, которое показывает, сколько секунд действителен кэш с момента последнего запроса правильного ресурса.
- Истекает абсолютное время. Он используется для выражения того, что запрос, сделанный до этого момента времени, может напрямую считывать данные из браузера без выполнения запроса.
- Cache-Control имеет более высокий приоритет, чем Expires. Первый, по-видимому, решил проблему, связанную с тем, что Expires был изменен вручную во время браузера, что привело к неправильной оценке кеша.
- Cache-control используется, если присутствуют оба.
1) Сильный кеш - истекает
Это поле представляет собой поле заголовка ответа сервера, которое сообщает браузеру о необходимости доступа к данным непосредственно из кэша браузера до истечения срока действия.
Expires — это поле HTTP 1.0, указывающее время истечения кэша, которое является абсолютным временем (текущее время + время кэширования). В заголовке ответа после установки этого поля вы можете указать браузеру, что ему не нужно запрашивать снова, пока не истечет срок его действия.
Поскольку это абсолютное время, пользователь может изменить локальное время клиента, в результате чего браузер решит, что кеш недействителен, и снова запросит ресурс. Кроме того, даже если модификация не рассматривается, такие факторы, как разница во времени или ошибка, могут привести к тому, что время между клиентом и сервером будет несогласованным, что приведет к аннулированию кэша.
Преимущества:
- Продукт HTTP 1.0, может использоваться в HTTP 1.0 и 1.1, прост в использовании.
- Время истечения отмечено временем.
Неполноценность:
- Время отправляется сервером (UTC), если время сервера и время клиента не совпадают, могут возникнуть проблемы.
- Существует проблема с версией, а модификации до истечения срока действия не зависят от клиента.
2) Сильный кеш-контроль кеша
После того, как стали известны недостатки Expires, в HTTP/1.1 добавлено поле Cache-control, в котором указывается максимально допустимое время кэширования ресурса, в течение которого клиенту не нужно отправлять запрос на сервер.
Разница между ними в том, что первое — это абсолютное время, а второе — относительное время. Ниже перечислены некоторыеCache-controlЧасто используемые значения для полей: (полный список см. в MDN)
-
max-age: максимально допустимое время. -
must-revalidate: если большеmax-ageвремя браузер должен отправить запрос на сервер, чтобы убедиться, что ресурс все еще действителен. -
no-cache: Не используйте сильный кеш, вам нужно проверить на сервере свежесть кеша. -
no-store: Настоящее "не кешировать". Весь контент не кэшируется, включая приведение и сравнение. -
public: Весь контент может быть кэширован (как клиенты, так и прокси, такие как CDN). -
private: весь контент может кэшироваться только клиентом, а не прокси-сервером. По умолчанию.
Cache-control имеет приоритет над Expires, чтобы быть совместимым с HTTP/1.0 и HTTP/1.1, оба поля могут быть установлены в реальном проекте.
Это поле может быть задано в заголовке запроса или в заголовке ответа и может сочетаться с различными командами:
-
кешируемость:
- общедоступный: по умолчанию и браузеры, и кеш-серверы могут кэшировать информацию о странице.
- частный: прокси-сервер не кэшируется и может кэшироваться только одним пользователем
- no-cache: ни браузер, ни сервер не должны кэшировать информацию о странице, но она все же может кэшироваться, но перед кэшированием необходимо подтвердить серверу, был ли изменен ресурс. Может использоваться с частным, Время истечения устанавливается равным прошлому времени.
- only-if-cache: клиент принимает только кешированные ответы
-
зрелость
-
max-age=<seconds>: Максимальный срок хранения кеша, по истечении которого он считается просроченным. -
s-maxage=<seconds>: Установить общий кеш, например можно. Переопределяет максимальный возраст и истекает. -
max-stale[=<seconds>]: клиент желает получить просроченный ресурс -
min-fresh=<seconds>: Клиент хочет получить последний ответ в течение указанного времени. -
stale-while-revalidate=<seconds>: Клиент хотел бы получить несвежий ответ и чек на новые ответы на заднем плане. Время от имени клиента хотелось бы получить несвежий ответ Продолжительность времени. -
stale-if-error=<seconds>: если новое обнаружение не удается, клиент готов получить устаревший ответ, а время представляет собой время ожидания.
-
-
Подтвердить и перезагрузить
- must-revalidate: если срок действия страницы истек, перейдите на сервер, чтобы получить ее.
- proxy-revalidate: для общих кешей.
- immutable: тело ответа не меняется со временем.
-
разное
- no-store: Полностью отключить кеширование
- no-transform: Ресурс нельзя преобразовывать и преобразовывать. Например, нельзя преобразовывать форматы изображений.
Преимущества:
- Продукт HTTP 1.1, определяющий время истечения по интервалу времени, решает проблему относительного времени между сервером Expires и клиентом.
- Вариантов гораздо больше, чем Expires.
Вопрос слабости:
- Существует проблема с версией, а модификации до истечения срока действия не зависят от клиента.
2. Согласовать кеш
Это позволяет клиенту и серверу проверять, обновлен ли кэшированный файл, повышать скорость повторного использования кэша и отправлять Etag и Last-Modified в кэшированной информации на сервер через запрос, и сервер проверяет это. возвращается код состояния 304. Браузер напрямую использует кеш.
- Код состояния кэша согласования определяется сервером для возврата 200 или 304.
- Когда сильный кеш браузера недействителен или заголовок запроса не имеет сильного кеша, а в заголовке запроса установлено if-Modified-Since или If-None-Match, эти два значения атрибута будут отправлены на сервер. Чтобы проверить, сработал ли кеш согласования, если кеш согласования сработал, будет возвращен статус 304, будет загружен кеш браузера, а в заголовке ответа будет установлен атрибут Last-Modified или ETag.
- Сравнение количества запросов с кешем согласуется с отсутствием кеша, но если это 304, он возвращает только код состояния, а фактического содержимого файла нет, поэтому сохранение размера тела ответа является его точкой оптимизации.
- Кэш согласования имеет 2 набора полей (а не два), а поля, которые управляют кэшем согласования: Last-Modified/If-Modified-since (http1.0) и Etag/If-None-match (http1.1).
- Last-Modified/If-Modified-since указывает время последней модификации ресурса сервера, Etag/If-None-match указывает уникальный идентификатор ресурса сервера.Пока изменяется ресурс, Etag будет перегенерирован.
- Etag/If-None-match имеет более высокий приоритет, чем Last-Modified/If-Modified-since.
1) Переговоры в кэш-переговорах в кэш-последнее модифицировано / если-модифицировано - с
- сервер через
Last-ModifiedПоле сообщает клиенту, когда ресурс был изменен в последний раз, например.Last-Modified: Mon, 10 Nov 2018 09:10:11 GMT - Браузер записывает это значение в базу данных кеша вместе с содержимым.
- В следующий раз, когда запрашивается тот же ресурс, браузер ищет кеш с неопределенным сроком действия в своем собственном кеше. Поэтому в заголовке запроса последний
Last-ModifiedЗначение записывается в заголовок запросаIf-Modified-Sinceполе - Сервер будет
If-Modified-Sinceзначение сLast-Modifiedполя для сравнения. Если они равны, это означает, что он не был изменен и отвечает кодом 304; в противном случае это означает, что он был изменен, и он отвечает кодом состояния 200 и возвращает данные.
Преимущества:
- Проблем с версией нет, и каждый запрос будет отправляться на сервер для проверки. Сервер возвращает 304, если время последней модификации совпадает, и возвращает 200 и содержимое ресурса, если оно отличается.
Вопрос слабости:
- Всякий раз, когда ресурс модифицируется, независимо от того, существенно ли изменилось содержимое, ресурс возвращается клиенту. Например, периодическая перезапись, когда ресурс содержит практически одни и те же данные.
- Используя время в качестве индикатора, невозможно распознать ситуацию, когда за одну секунду производится несколько модификаций. Если частота обновления ресурса составляет доли секунды, то кэш нельзя использовать, поскольку его минимальная единица времени — секунды.
- Некоторые серверы не могут получить точное время последней модификации файла.
- Если файл динамически генерируется сервером, время обновления этого метода всегда является временем генерации, хотя файл может и не изменяться, поэтому он не играет роли в кэшировании.
2) Согласовать cache-Etag/If-None-match
- В целях решения вышеуказанных проблем появился новый набор полей
Etagа такжеIf-None-Match -
EtagСохраняется специальный идентификатор файла (обычно генерируемый хэшем), а сервер хранит идентификатор файла.Etagполе. последующий процесс иLast-Modifiedпоследовательный, простоLast-ModifiedПоле и время обновления, которое оно представляет, изменены наEtagполе и хэш файла, который он представляет, поместитеIf-Modified-SinceсталIf-None-Match. Сервер выполняет такое же сравнение, возвращая 304 для попаданий и 200 для нового ресурса при промахах. - Когда браузер инициирует запрос, сервер возвращает уникальный идентификатор запрошенного ресурса в заголовке Response. В следующем запросе значение Etag, возвращенное в последний раз, будет присвоено If-No-Matched и добавлено в заголовок запроса. Сервер сравнивает отправленный браузером if-no-matched с ETag своего локального ресурса и, если он совпадает, возвращает 304, чтобы уведомить браузер о необходимости чтения локального кеша, в противном случае возвращает 200 и обновленный ресурс.
- Etag имеет приоритет над Last-Modified.
Преимущества:
- Он может более точно определить, был ли изменен ресурс, и может определить ситуацию множественных модификаций в течение одной секунды.
- Проблем с версией нет, и каждый запрос возвращается на сервер для проверки.
Вопрос слабости:
- Вычисление значения ETag требует снижения производительности.
- В случае с распределенным серверным хранилищем, если алгоритм вычисления ETag будет другим, это приведет к ситуации, когда ETag не совпадает, когда браузер получает содержимое страницы с одного сервера и проверяет его на другом сервере.
Во-вторых, браузер появляется с диска, из стратегии памяти.
Сильный кеш: сервер уведомляет браузер о времени кеша. В течение времени кеша следующий запрос будет использовать кеш напрямую. Если это не в пределах времени, будут выполнены другие стратегии кеша.
- Браузер обнаруживает, что данных в кеше нет, поэтому отправляет запрос на получение ресурсов с сервера
- Сервер отвечает на запрос, возвращает ресурс и отмечает срок действия ресурса
Cache-Contrl: max-age=3000 - Браузер кэширует ресурс и ждет следующего повторного использования
7. Страница со списком торгового центра переходит на страницу сведений о продукте. Интерфейс данных на странице сведений работает очень медленно. Как внешний интерфейс может оптимизировать взаимодействие с пользователем?
Компания: Айфанер
Категория: JavaScript
Посмотреть анализ
1. Оптимизированная сокращенная версия
1) Ленивая загрузка: получите данные первого экрана и сделайте запрос на скользящую загрузку данных позади
- Во-первых, помещайте адрес изображения не в атрибут src, а в другой атрибут (data-original).
- После загрузки страницы определить, находится ли изображение в поле зрения пользователя по данным scrollTop, и если да, то взять значение атрибута data-original и сохранить его в атрибуте src.
- В событии прокрутки неоднократно оценивается попадание изображения в поле зрения, если да, то значение атрибута data-original извлекается и сохраняется в атрибуте src.
2) Используйте каркасный экран, чтобы улучшить взаимодействие с пользователем.
3) Предварительная загрузка PreloadJS
Используя библиотеку PreloadJS, PreloadJS обеспечивает согласованный способ предварительной загрузки контента для использования в HTML-приложениях. Предварительная загрузка может быть выполнена с использованием тегов HTML, а также XHR. По умолчанию PreloadJS попытается загрузить контент с помощью XHR, поскольку он обеспечивает лучшую поддержку событий выполнения и завершения, но может быть лучше использовать загрузку на основе тегов из-за проблем с несколькими источниками.
4) В дополнение к добавлению внешней загрузки и тайм-аута 404 страниц, часть интерфейса может добавить кеш интерфейса и предварительную загрузку интерфейса.
- Использовать рабочую область для кэширования данных, приоритет кэширования
- Используйте orm для кэширования локальных автономных данных и сначала запрашивайте локальные данные.
- Используйте предварительную загрузку, а затем перейдите на этап страницы сведений и используйте быструю ссылку для предварительной загрузки страницы сведений.
- Используйте nodejs в качестве среднего уровня для кэширования данных страницы сведений в Redis и т. д.
Вышеуказанные методы могут использоваться в сочетании в соответствии с потребностями бизнеса.
2. Оптимизированная подробная версия
1. Откройте поиск Google в качестве примера
- Левая сторона синей разделительной линии представляет DOMContentLoaded браузера, когда исходный HTML-документ полностью загружен и проанализирован без ожидания завершения загрузки таблиц стилей, изображений и подфреймов;
- Красная разделительная линия представляет загрузку, когда вся страница и все зависимые ресурсы, такие как таблицы стилей и изображения, завершили загрузку.
Итак, нас можно условно разделить на
- Оптимизации перед TTFB
- Оптимизация рендеринга в браузере
2. Обработка перед получением данных, когда сеть слишком медленная
Прежде всего, обратимся к классической картинке, которая уже не может быть классической.
Среди них cnd находится на стадии dns, а dom рендерится на стадии обработки onload.
На приведенном выше рисунке так много шагов в процессе от продвижения для выгрузки до загрузки.С точки зрения взаимодействия с пользователем, если страница занимает более 4 секунд от загрузки до отображения, будет очень интуитивно понятное явление зависания.Позиция, соответствующая to load — окончание события onLoad, после чего строится дерево dom, но пользователю не обязательно важно, завершила ли текущая страница загрузку ресурсов; Часто, когда на странице начинают появляться видимые элементы, начинаютсяРозыгрыш первого контента FCPилипервый розыгрыш ФКВ этот момент начинается визуальный опыт пользователя, чтобыTTI (время взаимодействия), Появление интерактивных элементов означает, что начинается процесс взаимодействия с пользователем, после чего пользователи могут с удовольствием просматривать и использовать наши страницы;
Так что главная болевая точка этой проблемы — необходимость сократить время прибытия.TTIа такжеFCPвремя
Однако известно, что при входе на нашу страницу сведений скорость возврата данных интерфейса очень низкая,FCPа такжеFC, и ускоренное прибытиеTTI, нам нужно предварительно обработать нашу страницу
3. Обработка кеша данных страницы (кеш это хорошо)
первый разВойдите на страницу сведений, вы можете использовать схему скелета для моделированияFCОтображение и скелетная диаграмма, вы можете использовать фоновое изображение и встроенный стиль для отображения страницы сведений в первый раз и использовать интерфейс сведений для слишком медленных запросов.workerПроцесс, запрос интерфейса на детали отправляется в другой рабочий поток для запроса, и страница отображает другие элементы, которые вернули данные; когда возвращаются очень медленные данные, необходимо выполнить вебп на странице в соответствии с подписью идентификатора продукта как изображение ключа или эскиза продукта Кэш пути cnd localStorage, подпись идентификатора продукта помещается в файл cookie и устанавливается на httpOnly
Не в первый разПри входе на страницу сведений внешний интерфейс может запросить идентификатор cookie, подписанный соответствующим идентификатором продукта, через определенный интерфейс и прочитать кэшированные данные изображения продукта в localStorage, чтобы можно было сократить время отображения первого скелетного изображения. и прибыл быстроTTIВремя на взаимодействие с пользователем, а затем через рабочие данные переключить картинку высокой четкости
4. Обработка просроченных кэшированных данных (базовое управление — основное, LRU — вспомогательное)
Для обработки адреса кешированного изображения, хотя кешированное изображение помещается в localStorage, ограничений по размеру нет, но слишком много — это нехорошо.Здесь используется алгоритм LRU для очистки изображения и другого локального хранилища. Данные страницы сведений о localStorage имеют следующую структуру:
"读取后端的cookieID": {
"path": "对应cdn图片的地址",
"time": "缓存时间戳",
"size": "大小"
}
5. Основной процесс обработки кеша данных и просроченных данных кеша
6. Для запросов с большим количеством запросов (таких как угадайте, что вам нравится на странице сведений, рекомендуемые продукты и другие статические ресурсы с большими объемами данных)
- Поскольку они не относятся к информации, которую пользователь хочет получить сразу после ввода сведений, то есть они не относятся к целевому телу текущей страницы, поэтому их можно использоватьIntersection Observer APIНаблюдая за основным элементом, когда текущий основной элемент загружен, выполняется выделение сетевых ресурсов неосновного элемента, то есть, когда сеть простаивает, затем запрашиваются ресурсы, такие как угадать, что вам нравится, рекомендовать продукты и заключать сделки. с проблемой приоритета запроса
- Необходимо следить за тем, чтобы количество запросов в списке запросов текущей страницы сведений не превышало количество запросов текущего браузера, tcp максимальное количество http запросов
7. Когда рабочие данные возвращаются, появляетсямного картинокПроблемы с заменой webp или миниатюр соответствующих элементов (слишком много статических ресурсов)
Есть два сценария
-
На мобильной стороне для мобильной стороны, как правило, не так много изображений.Как правило, страница сведений о продукте не будет превышать 100 ресурсов изображений; в настоящее время выберите схему ленивой загрузки; в соответствии со многими существующими схемами на GitHub , текущее скольжение к наблюдаемому. Ресурс изображения текущей видимой области загружается только после того, как элементIntersection Observer API; например, библиотека vuevue-lazy, эта библиотека предназначена для инкапсуляции Intersection_Observer_API и замены атрибутов data-src и src заметок img в видимой области.
-
Во втором случае на стороне ПК может быть большое количество тегов img, которых может быть от 300 до 400. В настоящее время, используя отложенную загрузку, пользовательский опыт не очень хорош, например: пользователь просматривает введение в описание продукта , эти описания продуктов и введение могут быть просто изображениями.Когда пользователь проводит очень быстро, страница не была загружена лениво, и пользователь может не увидеть информацию, которую он хочет видеть; Ввиду этой ситуации, вот решение есть, img появляется одна загрузка одна, реализация такова:
// 这里针对非第一次进入详情页,
//当前localStorage已经有了当前详情页商品图片的缩略图
for(let i = 0; i < worker.img.length; i++) {
// nodeList是对应img标签,
// 注意, 这里对应的nodeList一定要使用内联style把位置大小设置好, 避免大量的重绘重排
const img = nodeList[i]
img.src = worker.img['path'];
img.onerror = () => {
// 将替换失败或者加载失败的图片降级到缩略图,
// 即缓存到localStorage的缩略图或者webp图
// 兼容客户端处理webp失败的情况
}
}
8. Обработка перерисовки страницы
Операции, запускающие перестановку, в основном геометрические:
- Отрисовка первой записи страницы.
- браузер изменить размер
- Когда положение и размер элемента меняются
- Добавление и удаление видимых элементов
- Содержание изменилось
- Шрифт шрифта меняется.
- Активация псевдокласса css. .....
Минимизируйте вышеуказанные операции, которые генерируют перерисовку и перекомпоновку
Например:
Большая перерисовка и переупорядочивание здесь в основном происходят на этапе замены изображения src на странице данными, возвращаемыми рабочим процессом.
// 该节点为img标签的父节点
const imgParent = docucment.getElementById('imgParent');
// 克隆当前需要替换img标签的父元素下所有的标签
const newImgParent = imgParent.cloneNode(true);
const imgParentParent = docucment.getElementById('imgParentParent');
for(let i = 0; i < newImgParent.children.length; i++) {
// 批量获取完所有img标签后, 再进行重绘
newImgParent.children[i].src = worker.img[i].path;
}
// 通过img父节点的父节点, 来替换整个img父节点
// 包括对应的所有子节点, 只进行一次重绘操作
imgParentParent.replaceChild(newImgParent, imgParent);
9. Обработка кода CSS
Остерегайтесь заблокированных ресурсов css
Как мы все знаем, загрузка css блокирует загрузку других ресурсов в браузере до тех пор, пока не появится CSSOM.CSS OBJECT MODELСборка завершена, а затем зависает в дереве DOM, браузер, в свою очередь, использует дерево рендеринга для компоновки и отрисовки веб-страницы.
Многие люди подсознательно знают, что файлы CSS лучше размещать в теге head, но зачем помещать CSS в тег head в конце?
Мы используем Taobao в качестве примера
Например, такая страница без стиля css называется FOUC (кратковременный сбой стиля содержимого), но такая ситуация обычно встречается в ie series и ранних браузерах, то есть когда cssom генерируется в domtree, он еще не закончен загрузка, Сначала отобразите страницу с чистым html-кодом, а затем появится правильная страница со стилем css;
Уменьшить загрузку кода css для разных страниц
Для страниц электронной коммерции некоторые CSS-коды в шапке отображаются на главной странице, а некоторые отображаются только в определенных ситуациях, например, когда нам нужно уменьшить размер некоторых CSS-файлов, но при этом нужно отображать текущий веб-сайт. на нескольких экранах многие люди подумают об этом. Это медиа-запрос, да, направление правильное, но какой медиа-запрос может сделать файл css достаточно маленьким? Вы можете использовать медиа-запрос тега ссылки, см. Пример ниже :
<link href="base.css" rel="stylesheet">
<link href="other.css" rel="stylesheet" media="(min-width: 750px)">
Первый ресурс css означает, что будут загружены все страницы, второй ресурс css, ширина будет загружена только при 750px, по умолчанию media="all"
Для некоторых веб-сайтов, которым необходимо писать медиа-запросы CSS, не пишите их в коде CSS. Лучше написать два набора кодов CSS и загружать их динамически с помощью связанных медиа-запросов, что может значительно снизить нагрузку на веб-сайты при загрузке CSS. файлы.
10. Обработка статического кода js
Этот вид js-кода связан с захоронением точек, локальным дневником, динамическим изменением css-кода и чтением некоторого js-кода после формирования страницы.Такой вид кода всегда размещается в localStorage под одним и тем же доменом. домен?
Вот пример Tmall
11. Отказоустойчивая обработка
- После того, как страница получает данные, возвращенные воркером, она копирует весь html-фрагмент, а затем добавляет путь img воркера к соответствующему узлу DOM после замены соответствующего ресурса img.
- Кэшируйте css-файлы и js-файлы в localStorage, если нет соответствующего css-файла или js-файла, или злонамеренно измененного css-файла или js-файла (вы можете судить по подписи), удалите его и получите обновление соответствующего файла
12. Причины для рекомендации плана
- Рабочий поток используется для запроса подробных данных, не занимая основной поток браузера, тем самым сокращая время, которое основной процесс занимает в сети.
- Используйте механизм кеширования localStorage, потому что, когда воркер возвращает данные, чтение localStorage читается синхронно, и времени ожидания в принципе нет, а при чтении localStorage для чтения используется cookieID, возвращаемый бэкендом, и локальный cookieID httpOnly, что позволяет третьей стороне не получать cookieID для чтения информации о продукте.
- Очистить лишние кэшированные данные с помощью LRU
- При первом входе на страницу обеспечьте быстрый рендеринг при известном макете страницы и настройте скелетную диаграмму, чтобы ускорить время достижения FCP и FP.
- Даже статический ресурс img слишком велик, в то время как во второй раз на этой странице вы также можете выполнить перестройку низкочастотной перерисовки, ускорение TTI в конце времени.
13. Недостаточные решения
- При условии, что сеть по-прежнему очень медленная, при первом входе на страницу сведений, если взаимодействие с пользователем по-прежнему неудовлетворительно в соответствии с долгосрочной скелетной диаграммой и известной компоновкой, здесь можно рассмотреть решение PWA для захвата содержимое последнего успешного запроса. , а в случае отсутствия сети сделать соответствующие подсказки и отобразить обработку
- На стороне пользовательского интерфейса требуются три набора статических ресурсов img.
8. Расскажите о принципе единого входа
Компания: ЦВТЭ
Категория: JavaScript
Посмотреть анализ
1. Что такое единый вход
Единый вход SSO (Single Sign On) — это мультисистемная среда сосуществования.После того как пользователь авторизуется в одном месте, ему не нужно авторизоваться в других системах, то есть одному логину пользователя доверяют все остальные системы.
Например, в существующих бизнес-системах A, B, C и системе SSO при первом доступе к системе A обнаруживается отсутствие входа в систему, и пользователю предлагается войти в систему SSO. учетной записи пользователя, генерируется уникальный токен учетных данных, который возвращается пользователю. Когда пользователи позже получают доступ к системам B и C, они приносят соответствующие учетные данные в систему SSO для проверки.После прохождения проверки они могут войти в систему с помощью единого входа;
Единый вход очень часто используется на крупных веб-сайтах. Например, у Alibaba есть веб-сайты Taobao, Tmall, Alipay и др. За ними стоят сотни подсистем. Одна операция или транзакция пользователя может включать множество подсистем. Каждая подсистема требует аутентификации. , поэтому предлагается, чтобы пользователи могли получить доступ к взаимно доверенным системам приложений после однократного входа в систему.
Одиночный вход имеет независимый центр аутентификации. Только центр аутентификации может принять имя пользователя и пароль пользователя для аутентификации. Другие системы не предоставляют входной записи и принимают только непрямое разрешение от центра аутентификации. Непрямое разрешение достигается через токены. После того, как имя пользователя и пароль, предоставленные пользователем, аутентифицированы Центром аутентификации, Центр аутентификации создаст токен авторизации. В следующем процессе скачка токен отправляется в каждую подсистему в качестве параметра , После получения токена он авторизован, а затем создается частичная сессия.
Во-вторых, принцип единого входа
Единый вход имеет два сценария: однодоменный и междоменный.
1) Тот же домен
Применимые сценарии: Все системы являются собственными системами предприятия, и все системы используют одно и то же доменное имя первого уровня, чтобы их можно было отличить по разным доменным именам второго уровня.
Например: у компании доменное имя первого уровня zlt.com, у нас три системы: система портала (sso.zlt.com), приложение 1 (app1.zlt.com) и приложение 2 (app2.zlt.com). , вам необходимо реализовать единый вход между системами, и архитектура реализации выглядит следующим образом.
Основной принцип:
- Домен файла cookie, установленного системой портала, представляет собой доменное имя первого уровня, а также zlt.com, чтобы файл cookie портала можно было использовать во всех системах, использующих доменное имя xxx.alt.com.
- Используйте такие технологии, как Spring Session, чтобы позволить всем системам совместно использовать сеанс.
- Таким образом, пока система портала входит в систему, независимо от того, переходите ли вы к приложению 1 или приложению 2, вы можете прочитать информацию для входа в сеансе через идентификатор сеанса в файле cookie портала для достижения единого входа.
2) Междоменный
Системные доменные имена различаются в системах единого входа, например, в сторонних системах. Поскольку доменное имя другое, куки нельзя расшаривать.Требуется независимая система авторизации, то есть независимый центр аутентификации (паспорт).Логин подсистемы может проходить паспорт, а сама подсистема в логине участвовать не будет Когда система успешно входит в систему, после этого passprot выдает токен для подсистемы, и подсистема может использовать токен для получения собственных ресурсов защиты. Чтобы уменьшить частоту аутентификации, каждая подсистема установит локальный сеанс после авторизован по паспорту, и он будет установлен в течение определенного периода времени.Не нужно повторно инициировать аутентификацию по паспорту
Фундаментальный
- Когда пользователь получает доступ к системе приложений в первый раз, потому что он не вошел в систему, он будет перенаправлен наСистема аутентификациичтобы залогиниться;
- В соответствии с информацией для входа, предоставленной пользователем, система аутентификации выполняет проверку личности и, если она пройдена, возвращает учетные данные аутентификации пользователю.жетон;
- Когда пользователь снова посещает другое приложение,Принесите токен в качестве учетных данных аутентификации;
- После того, как прикладная система получит запрос, она отправит токен на сервер аутентификации длячек об оплате, в случае прохождения пользователи могут получить доступ к другим доверенным бизнес-серверам без входа в систему.
Процесс входа
- Пользователь обращается к защищенным ресурсам системы 1, а система 1 обнаруживает, что пользователь не вошел в систему, переходит к центру аутентификации sso и использует собственный адрес в качестве параметра
- Центр аутентификации sso обнаруживает, что пользователь не вошел в систему, и направляет пользователя на страницу входа.
- Пользователь вводит логин и пароль для входа
- Центр аутентификации sso проверяет информацию о пользователе, создает сеанс между пользователем и центром аутентификации sso, который называется глобальным сеансом, и одновременно создает токен авторизации.
- sso возвращается к исходному запрошенному адресу с токеном (система 1)
- Система 1 удерживает токен и обращается к центру аутентификации sso, чтобы проверить, действителен ли токен.
- Центр аутентификации sso проверяет токен, возвращает действительный и регистрирует систему 1 (то есть возвращает файл cookie).
- Как только система использует токен для создания сеанса с пользователем, он становится локальным сеансом и возвращает защищенный ресурс.
- Доступ пользователей к защищенным ресурсам системы 2
- Система 2 обнаруживает, что пользователь не вошел в систему, переходит к центру аутентификации sso и использует собственный адрес в качестве параметра.
- Центр аутентификации sso обнаруживает, что пользователь вошел в систему, возвращается к адресу системы 2 и прикрепляет токен.
- Система 2 получает токен, обращается в центр SSO, чтобы проверить, действителен ли токен, возвращает действительность и регистрирует систему 2.
- Система 2 использует токен для создания частичного сеанса с пользователем, возвращая защищенный ресурс.
- После успешного входа пользователя в систему будет установлен сеанс с центром аутентификации SSO и каждой подсистемой. Сеанс, установленный пользователем и центром аутентификации SSO, называется глобальным сеансом, а сеанс, установленный пользователем и каждой подсистемой, называется локальный сеанс.После того, как локальный сеанс установлен, доступ пользователя к защищенным ресурсам подсистемы больше не будет проходить через центр аутентификации sso
процесс выхода
- Пользователь отправляет в систему операцию выхода
- Система получает токен в соответствии с сеансом, установленным между пользователем и системой 1, и отправляет операцию выхода в центр аутентификации sso.
- Центр аутентификации sso проверяет допустимость токена, уничтожает глобальный сеанс и удаляет все системные адреса, зарегистрированные с этим токеном.
- Центр аутентификации sso инициирует запрос на выход из системы во все системы регистрации, и каждая система регистрации уничтожает локальный сеанс.
- Центр аутентификации SSO направляет пользователя на страницу входа.
9. Расскажите о том, как уменьшить количество DOM? Как оптимизировать, чтобы дать вам много дома за один раз?
Компаний: 58
Категория: HTML
Посмотреть анализ
Во-первых, метод уменьшения количества DOM
- Можно использовать псевдоэлементы, а контент, реализованный тенями, не должен максимально реализовываться с использованием DOM, например очистка плавающих элементов, реализация стилей и т. д.;
- Загружайте по требованию, чтобы уменьшить ненужный рендеринг;
- Разумная структура и смысловые метки;
Во-вторых, оптимизация большого количества DOM
Когда ряд операций выполняется над элементами Dom, перерисовка и перестановка, вызванные доступом и изменением Dom, потребляют производительность.Поэтому в отношении работы Dom следует учитывать следующие моменты:
1. Кэшировать объект Dom
Во-первых, независимо от сценария. Общая операция Дома сначала пойдет на посещение Дома, тем более что сложность цикла в это время может быть относительно высокой. Это будет главный узел, узлу не нужно циклически выполнять Dom, чтобы стать первым, на него можно напрямую ссылаться в цикле перед циклом, без необходимости повторного запроса.
let rootElem = document.querySelector('#app');
let childList = rootElem.child; // 假设全是dom节点
for(let i = 0;i<childList.len;j++){
/**
* 根据条件对应操作
*/
}
2. Фрагменты документа
использоватьdocument.createDocumentFragment()Метод создает узел фрагмента документа, который является объектом виртуального узла. Добавьте узел dom к этому узлу, и изменение узла dom не повлияет на реальную структуру дома.
Мы можем воспользоваться этим, чтобы сначала изменить DOM, который нам нужно изменить, сохранить его во фрагменте документа, а затем одновременно заменить реальный узел DOM фрагментом документа. Подобно виртуальному дому, он также обеспечивает процесс перестановки и перерисовки, вызванный нечастым изменением дома.
let fragment = document.createDocumentFragment();
const operationDomHandle = (fragment) =>{
// 操作
}
operationDomHandle(fragment);
// 然后最后再替换
rootElem.replaceChild(fragment,oldDom);
Таким образом, будет запущена только одна перекомпоновка, и эффективность будет значительно повышена. Если нам нужно выполнить сложные операции над элементом (удалить, добавить дочерние узлы), то мы должны сначала удалить элемент со страницы, а затем оперировать с ним или скопировать его (cloneNode()) в память После выполнения операции , исходный узел заменяется.
var clone=old.cloneNode(true);
operationDomHandle(clone);
rootElem.replaceChild(clone,oldDom)
3. Используйте innerHtml вместо высокочастотного appendChild
4. Оптимальная схема компоновки
Пакетное чтение, однократная запись. Сначала поработайте с узлом, которого нет в дереве рендеринга, а затем добавьте узел обратно в дерево рендеринга. Это вызовет только одну операцию DOM. использоватьrequestAnimationFrame(), помещайте любые операции, вызывающие перерисовку, вrequestAnimationFrame
5. Виртуальный дом
js имитирует дерево DOM и работает с деревом DOM. Виртуальный DOM — это чистый js-объект (строковый объект), поэтому работать с ним будет эффективно.
Используя виртуальный дом, абстрагируйте дом в виртуальный дом, сначала используйте виртуальный дом при изменении дома, сравните структуру виртуального дома и исходного виртуального дома с помощью алгоритма diff dom и, наконец, измените структуру реального дома в пакетах. Избегайте частого изменения порядка и перерисовки, вызванных частая модификация DOM, насколько это возможно.
10. Реализуйте код по мере необходимости
/*
根据传入参数n(数字)对一维数组(纯数字)按照距离n最近的顺序排序。
(距离即数字与n的差值的绝对值)
*/
var arr = [7, 28, -1, 0, 7, 33];
function sort(n) {
//your code
}
Компания: Gaosi Education
Категория: Алгоритмы
Посмотреть анализ
Код
- Реализация 1: Гибкое применение метода сортировки
var arr = [7, 28, -28, 0, 7, 33];
function sort(n) {
arr.sort((a, b) => {
return Math.abs(a - n) - Math.abs(b - n);
})
console.log(arr);
}
sort(28);
- Реализация 2: Сортировка слияния на основе разрыва O (NLOGN)
var nearbySort = function (n, arr) {
var splitedArr = [];
for (var i = 0; i < arr.length; i++) {
splitedArr.push([arr[i]]);
}
while(splitedArr.length > 1) { // 两两一组,依次归并 ~ 递归就不用了~
var half = Math.ceil(splitedArr.length / 2);
for(var j = 0; j < half; j++) {
splitedArr[j] = mergeArr(n, splitedArr[j], splitedArr[j + half]);
}
console.log(half, splitedArr);
splitedArr.length = half;
}
return (splitedArr.length === 1) ? splitedArr[0] : [];
}
var getDistance = function (n, m){ // 获取n 与 m数值差异(绝对值)
return n > m ? (n - m) : (m - n);
}
var mergeArr = function(n, left, right){ // left right为已排序数组
if (!left) {
return right;
}
if (!right) {
return left;
}
var sortedArr = [], leftIndex = 0, rightIndex = 0, leftLen = left.length, rightLen = right.length;
while(leftIndex < leftLen || rightIndex < rightLen){
var leftNum = left[leftIndex], rightNum = right[rightIndex];
if (leftNum === undefined) {
sortedArr.push(rightNum);
rightIndex++;
} else if (rightNum === undefined) {
sortedArr.push(leftNum);
leftIndex++;
} else {
var leftDistance = getDistance(n, leftNum);
var rightDistanc = getDistance(n, rightNum);
if (leftDistance <= rightDistanc) {
sortedArr.push(leftNum);
leftIndex++;
} else {
sortedArr.push(rightNum);
rightIndex++;
}
}
}
return sortedArr;
}
- Для достижения трех: неизбежный разрыв будет отсортирован только фиксированным положительным целым числом, может создать хеш-таблицу {0: [], 1: [], .... N: []} Запись окончания, объединенная: сложность O (n) ;
var getDistance = function (n, m){ // 获取n 与 m数值差异(绝对值)
return n > m ? (n - m) : (m - n);
}
var nearbySort = function (n, arr) {
var distanceObj = {}, len = arr.length, distance, maxDistance = 0, result = [];
for(var i = 0; i < len; i++){
distance = getDistance(n, arr[i]);
if(distance > maxDistance){
maxDistance = distance;
}
if (distanceObj[distance]) {
distanceObj[distance].push(arr[i]);
} else {
distanceObj[distance] = [arr[i]];
}
}
for(var j = 0; j <= maxDistance; j++) { // 两层for, 但内层循环数固定, 总循环固定O(n);
if (distanceObj[j]) {
var eachDistance = distanceObj[j];
var eachLength = eachDistance.length;
for(var m = 0; m < eachLength; m++) {
result.push(eachDistance[m])
}
}
}
return result;
}