В Zingye есть фронтальные решения для оформления магазинов

программист внешний фреймворк

1. Введение

Учащиеся, которые занимались проектами электронной коммерции, знают, что оформление магазина является важной функцией системы электронной коммерции. В некоторых сценариях это может быть создание рекламных страниц, создание страниц действий и создание микространиц, но основные функции аналогичны. . Так называемое украшение магазина означает, что пользователи могут создавать мобильные страницы на стороне ПК, и им нужно всего лишь перетаскивать, чтобы реализовать редактирование страницы, что является очень индивидуальной функцией пользователей. Окончательный отредактированный результат можно отображать и продвигать в программах H5 и Mini.

иметь хвалебную кармуЭто система SaaS Saas Industry Industry Industry SaaS, которая предоставляет информационные технологии и интернет-решения для Соединенных Штатов в этой отрасли. Похвала и сама фитинговая индустрия похвалы обеспечивает функцию для облегчения пользователю настроить магазин, отображающий содержимое ниже, является функция скриншота.

有赞美业店铺装修

Изображение выше — это интерфейс на стороне ПК, а два изображения ниже — окончательный эффект отображения H5 и апплета соответственно. Можно просто увидеть, что сторона ПК в основном выполняет функции редактирования и предварительного просмотра страниц, включая богатые бизнес-компоненты и подробные параметры настройки; H5 и апплеты выполняют функцию окончательного отображения.

Давайте взглянем на текущие технические основы Youzianye: в настоящее время наша сторона ПК основана на стеке технологий React, сторона H5 основана на стеке технологий Vue, а Mini Program — это собственная модель разработки WeChat.

Исходя из этого, если мы хотим заниматься техническим проектированием, мы можем рассматривать со следующих точек зрения:

  • Все уровни просмотра трех терминалов управляются данными Как управлять потоком данных каждого терминала?

  • На трех терминалах три разных стека технологий, но в бизнесе один и тот же контент, есть ли возможность повторного использования кода?

  • Данные, окончательно сгенерированные ПК, должны быть переданы H5 и небольшим программам, а три терминала совместно используют набор данных.Какую форму следует использовать для стандартизации управления данными с трех терминалов?

  • О масштабируемости, как экономически эффективно поддерживать бизнес больше компонентов последующей деятельности, чтобы присоединиться?

2. Схемный дизайн

Поэтому мы разработали решение для решения вышеуказанных проблем в соответствии с техническими основами кармы хвалы.

Сначала выложите архитектурную диаграмму:

店铺装修架构图

2.1 Управление данными

Прежде всего, сосредоточьтесь на компоненте CustomPage, который является главной консолью для всего оформления магазина, он поддерживает три основных компонента, PageLeft, PageView и PageRight, которые соответствуют трем упомянутым выше модулям на стороне ПК.

Чтобы обеспечить совместное использование данных, CustomPage поддерживает «область» через контекст React, предоставляя «источник данных», общий для трех внутренних компонентов. PageLeft , PageRight — это левый компонент и правый компонент редактирования соответственно,context.pageДанные, изменения данных передаются черезcontext.pageChangeпередача. Весь процесс примерно выражается в коде следующим образом:

// CustomerPage
class CustomerPage extends React.Component {
    static childContextTypes = {
        page: PropTypes.object.isRequired,
        pageChange: PropTypes.func.isRequired,
        activeIndex: PropTypes.number.isRequired,
    };

    getChildContext() {
        const { pageInfo, pageLayout } = this.state;
        return {
            page: { pageInfo, pageLayout },
            pageChange: this.pageChange || (() => void 0),
            activeIndex: pageLayout.findIndex(block => block.active),
        };
    }
    
    render() {
    	return (
    		<div>
				<PageLeft />
            	<PageView />
            	<PageRight />
    		</div>
    	);
    }
}

// PageLeft
class PageLeft extends Component {
    static contextTypes = {
        page: PropTypes.object.isRequired,
        pageChange: PropTypes.func.isRequired,
        activeIndex: PropTypes.number.isRequired,
    };
    
    render() {...}
}


// PageRight
class PageRight extends Component {
    static contextTypes = {
        page: PropTypes.object.isRequired,
        pageChange: PropTypes.func.isRequired,
        activeIndex: PropTypes.number.isRequired,
    };
    
    render() {...}
}

Что касается стороны H5, динамические компоненты Vue можно использовать для завершения динамизации бизнес-компонентов.Этот метод асинхронных компонентов обеспечивает большую гибкость и очень подходит для сценариев оформления магазина.

<div v-for="item in components">
	<component :is="item.component" :options="convertOptions(item.options)" :isEdit="true">
	</component>
</div>

Поскольку апплет не имеет концепции динамических компонентов, он может передавать толькоif elseСпагетти-код для достижения этой функции. Если мы подумаем о повторном использовании более глубоко, в сообществе есть инструменты с открытым исходным кодом для реализации преобразования между Vue и апплетом, которые могут помочь нам сделать больше, но мы не будем обсуждать это здесь.

Данные, сгенерированные при редактировании на ПК, в конечном итоге будут переданы H5 и апплету, поэтому очень важно согласовать формат данных и значение поля. Чтобы решить эту проблему, мы извлекли пакет npm для управления объединением данных с 3 терминалов. Этот пакет описывает формат поля и значение каждого компонента.При реализации каждой стороне нужно только разработать соответствующий стиль в соответствии с описанием поля, что также решает проблему масштабируемости. Если в будущем вам потребуется добавить новые бизнес-компоненты, вам нужно будет только согласовать и обновить новый пакет npm, чтобы добиться унификации данных с трех сторон.

/**
 * 显示位置
 */
export const position = {
    LEFT: 0,
    CENTER: 1,
    RIGHT: 2,
};

export const positionMap = [{
    value: position.LEFT,
    name: '居左',
}, {
    value: position.CENTER,
    name: '居中',
}, {
    value: position.RIGHT,
    name: '居右',
}];

2.2 Межтерминальное мультиплексирование

PageView — это компонент предварительного просмотра, который является сердцем этого дизайна. По самой прямой идее, мы можем использовать React для реализации всех бизнес-компонентов, а затем снова реализовать логику упорядочивания и отображения данных, затем реализовать все компоненты в H5 и апплете, и снова реализовать логику упорядочивания и отображения данных. Но учитывая повторное использование кода, можем ли мы сделать что-то «ленивое»?

Если мы не рассматриваем апплет, мы знаем, что и ПК, и H5 реализованы на основе стиля dom, а логика также является кодом js, Если оба конца реализованы один раз, необходимо выполнить много повторяющейся работы. Итак, чтобы добиться возможности повторного использования стиля и логики, мы придумали способ вложения страниц H5 через iframe и взаимодействия с данными через postmessage, реализуя таким образом использование H5 в качестве компонента предварительного просмотра, затем код ПК и H5. это только один набор. В соответствии с этой идеей реализации компонент PageView может быть реализован следующим образом:

class PageView extends Component {
	render() {
        const { page = {} } = this.props;
        const { pageInfo = {}, pageLayout = [] } = page;
        const { loading } = this.state;
	
       return (
	        <div className={style}>
	            <iframe
	                title={pageInfo.title}
	                src={this.previewUrl}
	                frameBorder="0"
	                allowFullScreen="true"
	                width="100%"
	                height={601}
	                ref={(elem) => { this.iframeElem = elem; }}
	            />
	        </div>);
	    }
}

Код PageView очень прост, он заключается во встраивании iframe, а остальная работа возложена на H5. H5 преобразует полученные данные в соответствующее отображение массива компонентов в соответствии со спецификацией:

<template>
    <div>
        <component
            v-for="(item, index) in components"
            :is="item.component"
            :options="item.options"
            :isEdit="false">
        </component>
    </div>
</template>
<script>
    computed: {
        components() {
            return mapToComponents(this.list);
        },
    },
</script>

Из-за iframe нам также необходимо использовать postmessage для кросс-сорсинговой коммуникации.Для удобства использования мы сделали слой инкапсуляции (код см. в Self-Zan Catering):

export default class Messager {
    constructor(win, targetOrigin) {
        this.win = win;
        this.targetOrigin = targetOrigin;
        this.actions = {};
        window.addEventListener('message', this.handleMessageListener, false);
    }

    handleMessageListener = (event) => {
        // 我们能相信信息的发送者吗?  (也许这个发送者和我们最初打开的不是同一个页面).
        if (event.origin !== this.targetOrigin) {
            console.warn(`${event.origin}不对应源${this.targetOrigin}`);
            return;
        }
        if (!event.data || !event.data.type) {
            return;
        }
        const { type } = event.data;
        if (!this.actions[type]) {
            console.warn(`${type}: missing listener`);
            return;
        }
        this.actions[type](event.data.value);
    };

    on = (type, cb) => {
        this.actions[type] = cb;
        return this;
    };

    emit = (type, value) => {
        this.win.postMessage({
            type, value,
        }, this.targetOrigin);
        return this;
    };

    destroy() {
        window.removeEventListener('message', this.handleMessageListener);
    }
}

Исходя из этого, бизнес-сторона должна обращать внимание только на обработку сообщения.Например, компонент H5 может использовать следующее для получения обновлений данных с ПК:

this.messager = new Messager(window.parent, `${window.location.protocol}//mei.youzan.com`);
this.messager.on('pageChangeFromReact', (data) => {
	...
});

Таким образом, через события, согласованные с обеих сторон, достаточно обрабатывать бизнес-логику отдельно.

Здесь нужно разобраться с одной деталью, потому что высота предварительного просмотра будет динамически изменяться, а ПК должен контролировать высоту внешнего вида, поэтому должен быть механизм для динамического получения высоты предварительного просмотра. .

// vue script
updated() {
    this.$nextTick(() => {
    	const list = document.querySelectorAll('.preview .drag-box');
	    let total = 0;
	    list.forEach((item) => {
	        total += item.clientHeight;
	    });
	    this.messager.emit('vueStyleChange', { height: total });
    }
}

// react script
this.messsager.on('vueStyleChange', (value) => {
    const { height } = value;
    height && (this.iframeElem.style.height = `${height}px`);
});

2.3 Реализация перетаскивания

Функция перетаскивания реализована через API перетаскивания HTML5. В этом требовании основной целью является достижение эффекта динамической сортировки компонентов в процессе перетаскивания. Вот несколько ключевых моментов, реализация которых может потребовать некоторых усилий:

  • Вид автоматически прокручивается при перетаскивании вверх и вниз
  • Перетащите результаты, чтобы синхронизировать изменения данных
  • правильная анимация

В настоящее время в сообществе есть много зрелых библиотек, связанных с перетаскиванием, и мы выбираем vuedraggable. Причина тоже очень проста: с одной стороны, это позволяет избежать повторения создания колес, а с другой стороны, очень хорошо решает проблемы, о которых мы говорили выше.

vuedraggable очень хорошо инкапсулирован и очень прост в использовании.Инкапсулируйте динамические компоненты, о которых мы упоминали ранее, с помощью другого слоя перетаскиваемых компонентов:

<draggable
    v-model="list"
    :options="sortOptions"
    @start="onDragStart"
    @end="onDragEnd"
    class="preview"
    :class="{dragging: dragging}">
    <div>
        <component
            v-for="(item, index) in components"
            :is="item.component"
            :options="item.options"
            :isEdit="false">
        </component>
    </div>
</draggable>

const sortOptions = {
    animation: 150,
    ghostClass: 'sortable-ghost',
    chosenClass: 'sortable-chosen',
    dragClass: 'sortable-drag',
};

// vue script
computed: {
    list: {
        get() {
            return get(this.designData, 'pageLayout') || [];
        },
        set(value) {
            this.designData.pageLayout = value;
            this.notifyReact();
        },
    },
    components() {
        return mapToComponents(this.list);
    },
},

3. Резюме

На данный момент все конструкции готовы. Подводя итог, можно сказать, что совместное использование данных между компонентами на стороне ПК в основном осуществляется через контекст React; H5 и апплет отображаются через соответствующий компонентный массив сопоставления данных; основной задачей является достижение повторного использования логики стиля через iframe; унификация данных спецификации могут быть выполнены через сторонние пакеты npm.

Конечно, в дополнение к базовой архитектуре, есть еще много технических деталей, с которыми нужно разобраться, например, необходимость убедиться, что компонент предварительного просмотра не кликабельный и т. д. С этим нужно разобраться в фактической разработке.