1. Введение
В продуктах электронной коммерции (вы можете открыть свои приложения Taobao, Tmall и Jingdong), скрывая данные о воздействии продукта, вы можете изменить поведение пользователя и привычки взаимодействия, чтобы оптимизировать рекомендации и алгоритмы поиска и взаимодействия, и, наконец, цель, конечно, увеличить покупательную способность пользователей.
Экспозиция: Продукт появляется перед пользователем, то есть в окне браузера, что можно охарактеризовать как экспозицию.
Два самых простых способа
- 1. Слушайте события прокрутки через[Element.getBoundingClientRect() — Справочник по интерфейсу веб-API | MDN]Рассчитать положение предмета и окна
- 2. На странице работает таймер, который регулярно подсчитывает положение товара и окна.
Можно использовать оба метода, ноgetBoundingClientRectЭтот API вызовет переформатирование страницы, а неправильное использование может легко привести к проблемам с производительностью.
На основе этого браузер специально создал[Intersection Observer API - Web API | MDN], чтобы иметь дело с деталями, связанными с производительностью, чтобы разработчики заботились только о бизнес-логике
Во-вторых, INTERSECTION OBSERVER API
Весь план точки воздействия основан на[Intersection Observer API — Справочник по интерфейсу веб-API | MDN]
Этот API все еще относительно новый, что касается проблем с совместимостью.[IntersectionObserver/polyfill· w3c]решить по существуgetBoundingClientRectРассчитать расположение, как это реализовать можно в его исходниках
В-третьих, идея захоронения данных
-
new IntersectionObserver()Примеры глобального_observer, каждый продукт DOM добавляет себя_observerСписок наблюдения (это будет реализовано с помощью директив Vue) - Когда DOM продукта входит в окно, собирайте информацию о продукте и сохраняйте ее в глобальном массиве.
dotArr, а затем отменить наблюдение за товарным DOM - от
dotArrСравнительно просто взять данные из
- Запускаем таймер, проверяем его каждые N секунд и сообщаем напрямую, если в dotArr есть данные;
- Если в течение N секунд
dotArrОбъем данных превышает определенное количествоmaxNum, не дожидаясь таймера, сообщать обо всем напрямую
- Среда браузера:
dotArrВ то же время существуетlocalStorage, синхронно обновить данные (добавить или очистить после отчета), если пользователь действительно находится в интервале N секунд, а данных недостаточно, чтобы сообщить максимальное количествоmaxNumКогда левая страница, то эти данные в следующий раз, когда пользователь на другой странице, непосредственно изlocalStorageКонечно, если пользователь больше никогда не заходит на страницу и не очищает кеш браузера, эта небольшая потеря данных приемлема. - Среда веб-просмотра на стороне клиента: зарегистрируйте событие закрытия веб-просмотра (требуется поддержка детской обуви на стороне клиента) и уничтожьте все перед выходом.
В-четвертых, реализация кода
1. Инкапсулируйте класс экспозиции
// polyfill
import 'intersection-observer';
// 自行封装数据上报方法,其实就是网络请求
import { DotData } from './DotData'
// 可以把节流的时间调大一点,默认是100ms
IntersectionObserver.prototype['THROTTLE_TIMEOUT'] = 300;
export default class Exposure {
dotDataArr: Array<string>;
maxNum: number;
// _observer可以理解为观察者的集合吧
_observer;
_timer: number;
constructor(maxNum = 20) {
// 当前收集的 尚未上报的数据 也就是已经进入视窗的DOM节点的数据
this.dotDataArr = [];
this.maxNum = maxNum;
this._timer = 0;
// 全局只会实例化一次Exposure类,init方法也只会执行一次
this.init();
}
init() {
const self = this;
// init只会执行一次,所以这两边界处理方法放这就行
// 把浏览器localStorage里面的剩余数据打完
this.dotFromLocalStorage();
// 注册客户端webview的关闭生命钩子事件
this.beforeLeaveWebview();
this._observer = new IntersectionObserver(function (entries, observer) {
entries.forEach(entry => {
// 这段逻辑,是每一个商品进入视窗时都会触发的
if (entry.isIntersecting) {
// 清楚当前定时器
clearTimeout(self._timer);
// 我这里是直接把商品相关的数据直接放DOM上面了 比如 <div {...什么id class style等属性} :data-dot="渲染商品流时自行加上自身属性" ></div>
const ctm = entry.target.attributes['data-dot'].value;
// 把收集到的数据添加进待上报的数据数组中
self.dotDataArr.push(ctm);
// 收集到该商品的数据后,取消对该商品DOM的观察
self._observer.unobserve(entry.target);
// 超过一定数量打点,打完点会删除这一批
if (self.dotDataArr.length >= self.maxNum) {
self.dot();
} else {
self.storeIntoLocalstorage(self.dotDataArr);
if (self.dotDataArr.length > 0) {
//,只要有新的ctm进来 接下来如果没增加 自动2秒后打
self._timer = window.setTimeout(function () {
self.dot();
}, 2000)
}
}
}
})
}, {
root: null,
rootMargin: "0px",
threshold: 0.5 // 不一定非得全部露出来 这个阈值可以小一点点
});
}
// 每个商品都会会通过全局唯一的Exposure的实例来执行该add方法,将自己添加进观察者中
add(entry) {
this._observer && this._observer.observe(entry.el)
}
dot() {
// 同时删除这批打点的ctms
const dotDataArr = this.dotDataArr.splice(0, this.maxNum);
DotData(dotDataArr);
// 打完点,也顺便更新一下localStorage
this.storeIntoLocalstorage(this.dotDataArr);
}
storeIntoLocalstorage(dotDataArr) {
// 。。。 存进localStorage中,具体什么格式的字符串自行定义就好
}
dotFromLocalStorage() {
const ctmsStr = window.localStorage.getItem('dotDataArr');
if (ctmsStr) {
// 。。。如果有数据,就上报打点
}
}
beforeLeaveWebview() {
let win: any = window;
// 自行跟客户端童鞋约定该钩子的实现就好
injectEvent("webviewWillDisappear", () => {
if (this.dotDataArr.length > 0) {
DotData(this.dotDataArr);
}
})
}
}
2. Создание экземпляра Vue + инструкции по упаковке
[Пользовательская директива — Vue.js]
// 入口JS文件 main.js
// 引入Exposure类
// exp就是那个全局唯一的实例
const exp = new Exposure();
// vue封装一个指令,每个使用了该指令的商品都会自动add自身进观察者中
Vue.directive('exp-dot', {
bind(el, binding, vnode) {
exp.add({el: el, val: binding.value})
}
})
3. Использование товаров
Просто используйте команду для каждого элемента во время цикла
:data-dot="item.dotData"это данные, которые мы собираемся собрать
<div
v-exp-dot
v-for="item in list"
:key="item.id"
class=""
:data-dot="item.dotData"
>
// ...
</div>
В первоначальном плане мы намерены каждый раз вручную инициировать наблюдение за партией продуктов, например, подтягивание и загрузка для создания партии новых продуктов, ручная интерактивная загрузка партии новых продуктов и т. д., и непосредственно управлять экземпляр наблюдателяосматриватьЭта новая партия
Позже выяснилось, что завязка с бизнес-логикой слишком тяжелая, и не обязательно все товары на странице отрисовываются массивом в послушном порядке, также могут быть разные ресурсные биты и разные причины их появления. , лучше пусть каждый продукт срабатывает самнаблюдать
5. Еще
Спасибо за ваше терпение, чтобы увидеть здесь, и я надеюсь, что вы узнаете что-то!
Мне нравится делать записи в процессе обучения. Я делюсь некоторыми своими накоплениями и размышлениями о начальном этапе. Я надеюсь общаться с вами и добиваться прогресса. Дополнительные статьи см.[блог амандакелаке на Github]
Ссылаться на
[Тест статистики экспозиции на основе IntersectionObserver | xgfe]
[Анализ причин и решения для потери RBI перед разгрузкой]