В этой статье представлены мои недавние идеи реализации для аналогичных каскадных функций в провинциальных и муниципальных каскадах. Чтобы максимально разделить обязанности, производительность и поведение, эта функция разделена на 2 компонента, а один связанный список используется для реализации ключевой логики каскада. Следующий раздел имеет демонстрационный эффект. Хотя это очень распространенная функция, логика реализации этой статьи ясна, и код легко понять. Он отделен от семантики провинциальных и муниципальных каскадов и учитывает разделение производительности и поведения. Я надеюсь, что содержание этой статьи может принести некоторую справочную ценность в вашу работу. Добро пожаловать, чтобы прочитать и исправить это.
Каскадная каскадная операция
Каскадетип. Постоянная каскадная настойчивость (спасение)
Каскадетип. Операция обновления Cascade Cascade (Mergy)
Каскадетип. Обновить каскадную работу обновления, только запросить и получить операции
Каскадетип. Удалить операцию удаления каскада
Каскадетип. Все каскад все операции выше
Неужели задержать загрузку запчасти, по умолчанию состоит в том, что первая сторона загружается немедленно, а больше сторона - задержка загрузки
Сопоставление об обслуживании отношений
MapedBy = "ParentId" означает, что атрибут ParentID в классе детей используется для поддержания отношений. Это имя должно быть точно таким же, как и имя атрибута ParentId в классе детей.
Кроме того, следует отметить, что тип сбора в родительском классе должен быть список или установлен, и не может быть установлен в ArrayList, в противном случае будет сообщена ошибка
Демонстрационный эффект (загрузка кода, примечание. Этот эффект требует, чтобы HTTP работал. Кроме того, данные в эффекте являются моделируемыми данными и фактически не возвращаются на фоне, поэтому раскрывающиеся данные провинций, городов и округов, которые вы видите, одинаковы):
Примечание. В этой статье используется техническая реализация предыдущих нескольких связанных блогов. Если вам это нужно, вы можете нажать на ссылку ниже, чтобы узнать об этом:
1) подробное объяснение реализации наследования JavaScript: предоставьте класс.
2) навыки JQUERY, чтобы сделать любую поддержку компонентов DOM-подобные управление событиями: предоставить EventBase.js для предоставления любого экземпляра компонента с DOM-подобными функциями управления событиями;
3) Вторичная инкапсуляция прокси -компонентов Ajax и Ajax Cache Cache: AjaxCache: предоставляет ajax.js и ajaxcache.js, упрощает вызовы jquery и кэш -прокси для запросов клиентов.
Давайте сначала узнаем больше о требованиях этой функции.
1. Функциональный анализ
Эта функция иллюстрируется каскадным компонентом, содержащим три каскадных элемента:
1) Каждый каскадный элемент может потребовать опции, которая будет использоваться в качестве ввода:
В этом случае пустая опция может быть выбрана в списке данных каждого каскадного элемента (то есть тот, который вызван входом):
Также не потребуется использовать в качестве входных подсказок:
В этом случае только опция данных может быть выбрана в списке данных каждого каскадного элемента, и не может быть выбрана пустая опция:
2) Если текущая страница запрашивается из базы данных, а поля, соответствующие каскадному компоненту, имеют значения, то запросное значение повторяется на каскадном компоненте:
Если соответствующее поле, найденное в запросе, не имеет значения, то отображаются две ситуации, описанные в требованиях точки 1).
3) Каждый каскадный элемент образует одно связанное отношение списка в структуре данных. Список данных последнего каскадного элемента связан с данными, выбранными предыдущим каскадным элементом.
4) Учитывая проблемы с производительностью, список данных каждого каскадного элемента отображается Ajax асинхронно.
5) После завершения инициализации каскадного компонента список первого каскадного элемента автоматически загружается.
6) Когда текущий каскадный элемент меняется, очистите список данных всех каскадных элементов, которые прямо или косвенно связаны. В то же время, если значение после предыдущего каскадного элемента не является пустым, список данных следующего каскадного элемента, который непосредственно связан с ним, будет автоматически загружен. При очистке списка данных каскадных элементов, будьте осторожны: если каскадные элементы должны отобразить опцию приглашения ввода, опция должна быть сохранена при очистке.
7) Мы должны полностью рассмотреть проблемы с производительностью и избежать дублирования нагрузки.
8) Рассматривая проблему подчинения формы, когда любой каскадный элемент каскадного компонента изменяется, значение, выбранное каскадным компонентом, должно быть отражено в скрытом текстовом поле, чтобы облегчить представление значения каскадного компонента на фоне через текстовое поле.
Функция примерно, как указано выше.
2. Идеи реализации
1) Структура данных
Что отличается от других компонентов, так это то, что он имеет некоторые зависимости с данными в фоновом режиме. Структура данных, которую я считаю, лучше реализована:
{"id": 1, "text": "beijing", "code": 110000, "parentid": 0}, {"id": 2, "text": "провинция Hebei", "Код": 220000, "ParentId": 0}, {"id": 3, "Текст": "Провинция Henan", ",": 3300, родитель ":") ": 0: 0: 0: 0: 0)": ".Идентификатор является уникальным идентификатором данных, а связь ассоциации между данными построена через ParentID. Текст и код - все обычные деловые поля. Если мы следуем этой структуре данных, будет очень просто запросить интерфейс списка данных каскадных данных:
// Проверьте список первого каскадного элемента/API/Cascade? ParentId = 0 // Проверьте список второго каскадного элемента на основе значения, выбранного первым каскадным элементом/API/CASCADE? ParentID = 1 // Проверьте список третьего каскадного элемента, основанного на значении, выбранном вторым элементом Cascade/API/Cascade? ParentId = 4 ParentId = ParentId = ParentId = ParentId = ParentID
Эта структура также легко справиться с фоном. Несмотря на то, что они являются структурно структурой таблицы в форме дерева, все запросы являются однослойными, поэтому их легко реализовать.
Из предыдущей демонстрации запроса также можно увидеть, что эта структура может помочь нам объединить интерфейс и параметры запроса данных в один, что является очень удобной вещью для разработки компонентов. После того, как мы получим эту структуру данных из фона, мы разрабатываем каждые данные в опцию, такой как <vitor value = "peciging" data-param-value = "1"> Пекин </option>. Это может не только завершить раскрывающееся отображение списка данных, но и собрать выбранное значение текущего каскадного элемента через функцию элемента Select Form. Наконец, при изменении каскадного элемента мы также можем получить выбранную опцию и использовать значение значения данных, хранящихся на нем в качестве параметра ParentID для загрузки списка следующего каскадного элемента. Это также идея каскадных запросов данных компонентов и анализа.
Однако здесь необходимо рассмотреть вопрос о гибкости. В фактических проектах структуры данных каскадных компонентов могут быть определены в соответствии с аналогичными отношениями ассоциации, такими как ID ParentId, но их поля не обязательно называются текстовым кодом ID ParentID и, вероятно, будут другие поля. Другими словами: при анализе данных в опцию поле, используемое для текста и значения опции, и значение поля, используемого для атрибута V-Value Data, являются неопределенными; Имя параметра ParentId, используемое при запросе данных, не может быть мертвы. Иногда, если бэкэнд -персонал сначала пишет интерфейс запроса и использует другое имя, вы не можете попросить кого -то изменить имя своего параметра, потому что его необходимо собирать и развернуть, что является более хлопотным, чем передняя часть; Значение ParentID = 0 не может быть исправлено, потому что ParentId первого уровня данных в фактическом проекте может быть пустым или -1. Эти вещи должны быть спроектированы как варианты. С одной стороны, значение по умолчанию предоставляется, и внешняя настройка также зарезервирована в соответствии с фактической ситуацией. Например, в окончательной реализации этой статьи этот вариант определяется так:
Textfield: 'Text', // Имя поля в возвращаемых данных, которые будут отображаться в элементе <poion>
valuefield: 'text', // имя поля в возвращаемых данных, которые будут установлены на значении элемента <poion>
Paramfield: 'id', // При вызове интерфейса запроса данных имя поля, соответствующее данным, которые будут переданы на фону
ParamName: 'ParentId', // При вызове интерфейса запроса данных имя параметра данных передается после URL -адреса
DefletParam: '', // При запросе первого каскадного элемента значение, передаваемое на фон, обычно 0, '' или -1 и т. Д., Что указывает на то, что данные в верхнем уровне должны быть запрошены
2) Структура HTML
Согласно статье 1 предыдущего функционального анализа, существуют два типа начальных HTML -структур каскадных компонентов:
<ul id = "licenseLocation-view"> <li> <select> <option value = "> Пожалуйста, выберите провинцию </option> </select> </li> <li> <select> <опция value ="> Пожалуйста, выберите город </option> </select> </li> <li> <seumpt> <опция value = "> Пожалуйста, выберите район и округ </select> </select> </li> </li> </li> </li> </li> </li> </li> </li> </li> </li> </li> </li> </select> <опция =" ">« Пожалуйста
или
<ul id = "companyLocation-view"> <li> <select> </select> </li> <li> <select> </select> </li> <li> <li> <select> </select> </li> </ul>
Единственная разница между этими двумя структурами заключается в том, настроен ли настроенный вариант, используемый в качестве входных подсказок. Следует также отметить, что, если этот пустой вариант необходим, атрибут значения должен быть установлен на пустые, в противном случае этот пустой вариант отправит информацию о приглашении на фон при отправке формы.
Самая важная вещь в этих двух структурах - это избранное элемент, который не имеет ничего общего с UL и LI. UL и LI используются для пользовательского интерфейса; В избранном элементе нет семантики, и нет необходимости определять, какая провинция, которая является городом, а какой округ или округ. Функционально говоря, выбор представляет каскадный элемент. Неважно, где эти выборы определены. Нам просто нужно сообщить о каскадном компоненте, который выбирает элементы, из которых составлены его каскадные элементы. Единственное, что нужно сообщить компоненту, - это последовательность этих избранных элементов, но это обычно контролируется порядок по умолчанию элементов в HTML. Эта структура может помочь нам как можно больше отделить функции компонентов от поведения.
3) Разделение обязанностей и использование отдельных связанных списков
Из предыдущей части можно увидеть, что если этот каскадный компонент разделен в соответствии с обязанностями, его можно разделить на два основных компонента, один отвечает за управление общими функциями и внутренними каскадными элементами (Cascadeview), а другой отвечает за функциональную реализацию каскадных элементов (CascadeTem). Кроме того, чтобы более удобно реализовать логику каскадности, нам нужно только подключить все каскадные элементы через связанный список. Через режим Publish-Subscribe последний каскадный элемент подписывается на сообщение, что предыдущий каскадный элемент изменился; Когда текущий каскадный элемент меняется, публикуется сообщение для уведомления последующего каскадного элемента для обработки соответствующей логики; Благодаря роли связанного списка это сообщение может быть передано до последнего каскадного элемента. Если вы опишите это на картинке, это будет примерно так:
Все, что нам нужно сделать, это контролировать выпуск и доставку хороших новостей.
4) Форма подчинения
Чтобы удобно отправить значение каскадного компонента на фон, весь каскадный компонент может рассматриваться в целом, а снаружи предоставляется озаглавленное событие, через которое внешнее событие может получить значения всех каскадных элементов. Поскольку существует несколько каскадов, при публикации события Onchanged, это событие может быть вызвано только при изменении каскада.
5) Аяксский кеш
В этом компоненте мы должны рассмотреть два уровня кэша AJAX. Первый находится на уровне компонентов. Например, я переключил первый каскадный элемент на Пекин. В настоящее время второй каскадный элемент загрузил данные Пекина. Затем я переключил первый каскадный предмет с Пекина на Хэбэй, а затем на Пекин. В настоящее время второй каскадный элемент по -прежнему отображает связанный список данных Пекина. Если мы кэшировали его данные, когда список был сначала загружен, то нам не нужно инициировать запрос AJAX на этот раз; Второй - Ajax запрос. На уровне, если на странице есть несколько каскадных компонентов, я сначала переключаю первый каскадный элемент первого каскадного компонента в Пекин, и браузер инициирует запрос AJAX для загрузки данных. Когда я переключаю первый каскадный элемент второго каскадного компонента в Пекин, браузер отправит еще один запрос на загрузку данных. Если я кэширую данные, возвращаемые первым запросом AJAX первого компонента сначала, когда второй компонент использует те же параметры для запроса того же интерфейса, он будет напрямую использовать предыдущий кэш, чтобы вернуть результат, что также может уменьшить запрос AJAX. Второй уровень кэша AJAX зависит от вышеуказанной «вторичной инкапсуляции JQUERY AJAX и компонента CACE AJAX: AJAXCACHE». Для компонента он только реализует первый уровень кэша внутри, но ему не нужно учитывать второй уровень кэша, поскольку реализация кэша второго уровня является прозрачной, и он не знает, что компонент AJAX, который он использует, имеет функцию кэша.
3. Детали реализации
Окончательная реализация включает в себя три компонента, Cascadeview, Cascadeitem и Cascadepublicdefaults. Первые два являются ядром компонента, а последний просто используется для определения некоторых вариантов. Его функция подробно описана в комментариях Cascadeitem. Кроме того, в следующем коде есть очень подробные комментарии, которые объясняют роль некоторых ключевых кодов. Глядя на код на основе предыдущих требований, он должен быть относительно простым для понимания. Раньше я использовал текст, чтобы объяснить некоторые детали реализации, но позже я постепенно чувствовал, что этот метод был немного неблагодарным. Во -первых, язык на уровне деталей был нелегко организовать. Иногда я не выразил свой смысл. Я, очевидно, хотел что -то объяснить четко, но оказалось еще более запутанным. По крайней мере, я бы почувствовал это, когда прочитал то, что написал. Во -вторых, сами разработчики имеют возможность читать исходный код, и большинство активных разработчиков готовы понять идеи реализации, думая о коде других людей; Поэтому я использовал аннотацию для объяснения деталей реализации :)
Cascadepublicdefaults:
define (function () {return {url: '', // Query Interface TextField: 'Text', // возвращать данные в имени поля valuefield: 'text', // возвращать данные в имени поля, которые должны отображаться в элементе <pociate>, Paramfield: 'Text', // возвращать данные в поле поля, которые должны быть установлены на значении элемента «опция>», «Парафилд:», идентификатор «Идентификатор», // «Идентификатор Cropectory». Данные, которые должны быть переданы на фоновый фон: «ParentId», // При вызове интерфейса запроса данных имя параметра передачи данных после URL -адреса -DefaultParam: '', // При запросе первого каскадного элемента значение, передаваемое на фоновый Подсказка, например: Пожалуйста, выберите провинцию), если True, First OptionResolVeajax не будет очищен при перезагрузке каскадного элемента: function (res) {return res;} // Поскольку каскадный элемент будет отправлять асинхронный запрос при загрузке данных, этот вызов используется для анализа ответа, возвращаемого по асинхронному запросу});Cascadeview:
Определите (функция (require, exports, module) {var $ = require ('jquery'); var class = require ('mod/class'); var eventbase = require ('mod/eventbase'); var publicdefaults = require ('mod/cascadepublicdefaults'); var cascadeem = require ('mod/cascadiTem'); Cascadeitem Component*/var defaults = $. Пекинг -Сити, район, Чайангский район значений: '', // Строка, разделенная Valuesparator, представляет значение каждого выбора в начале onchanged: $ .noop // Это событие будет запускается, когда значение любого каскадного элемента}); this.base (); (i) {var $ el = $ (this); // создание создания компонента cascadeitem и укажите свойство Previtem каждого экземпляра на предыдущий экземпляр // Установить первое свойство Previtem на UndefinedVar cascadeem = new cascadeitem ($ el, $. $ .trim (values [i])})); item.push (cascadeitem); // Каждое изменение экземпляра каскада вызовет событие изменения компонента Cascadeview // может обрабатывать бизнес -логику в этом обратном вызове/, например, установить значения всех элементов Cascade в скрытое поле для формы Cascadem.on ('medie.CascAdeem, функция, функция, функция, функция, функция, функция (). {that.trigger ('medice.cascadeview', that.getValue ());});});}); // инициализация завершает автоматически загрузку первых каскадных элементов. () {return defaults;}, getItemoptions: function () {var opts = {}, _options = this.options; for (var i in publicDefaults) {if (publicDefaults.hashownproperty (i) && i in _option Каскадные элементы, которые представляют собой строку, разделенную Valuesparator // Значение пустого каскадного элемента не будет возвращать getValue: function () {var value = []; this.items.foreach (function (item) {var val = $ .trim (item.getValue ()); val! = '' && value.push (val); value.join (this.options.valueseparator);}}, extend: eventbase}); return cascadeview;});Cascadeitem:
Определите (function (require, exports, module) {var $ = require ('jquery'); var class = require ('mod/class'); var eventbase = require ('mod/eventbase'); var publicdefaults = require ('mod/cascadepublicdefaults'); varaxcache = reft ('mod/ajaxcache'); = new ajaxCache ();/*** Существует часть опции, определенной в PublicDefaults, поскольку компонент CascadeItem не будет использоваться непосредственно* Cascadeview компонент используется внешне, поэтому некоторые варианты должны стать публичными. PublicDefaults передается в CascadeItem*/var defaulte = $. это. Base; () Прокси -элемент SELECT {THE.Trigger ('medice.cascadeItem');}); // Когда изменяется значение каскадного элемента, обработка состоит в том, чтобы очистить и перезагрузить данные по мере необходимости. that.hascontent && that.clear (); // Если это не первый каскадный элемент, а предыдущий каскадный элемент не выбирает допустимый вариант, он не будет обрабатываться, если (that.previtem && $ .trim (that.previtem.getvalue ()) == ') return; '&& this.One (' render.cascadeTem ', function () {// Установить начальное значение, которое. $ el.val (value.split (', ')); // Уведомление последующего каскада для очистки и перезагрузки данных, которые. this.getDefaults (), options);}, getDefaults: function () {return defaults;}, clear: function () {var $ el = this. $ el; $ el.val ('' '); if (this.options. hepfirstoption) {// сохранить первый вариант $ el.children (). $ el.html ('');} // Уведомление о последующих элементах каскада для очистки и перезагрузки данных Данные первого каскадного элемента-это данные верхнего уровня, фиксированный и уникальный ключ используется, когда кэшируется: root // Имя ключа, используемое при кэшировании другими каскадными элементами, связано с опцией, выбранной предыдущим выбором if (! this.previtem) {paramvalue = opts.defaultparam; DACEAKEY = 'root'; this.previtem.getParamValue (); DataQuey = paramValue;} // сначала проверьте, есть ли загруженные данные в кэше данных, и если есть, оно будет отображаться непосредственно, чтобы избежать ajaxif (dataquey в this.cache) {this.render (this.cache [datakey]); paramvalue; ajax.get (opts.url, params) .done (function (res) {// resolveajax Этот обратный вызов используется для анализа данных, возвращаемых ajax внешним //. data; that.render (data);}});}}, повторное: function (data) {var html = [], opts = this.options; data.foreach (function (item) {html.push (['<option value = ", item [opts.valuefield],' 'data-param-value =", "/staric Свойство элемента опции [opts.paramfield], '">', item [opts.textfield], '</option>']. join (''));}); // Добавить динамически в форме добавления, чтобы избежать воздействия на первое опцию // в конце, установите значение, чтобы опустошить это. $ el.append (html.join ('')). this.trigger ('render.cascadeitem');}, getValue: function () {return this. $ el.val ();}, getParamValue: function () {return this. $ el.find ('опция: выбран'). Data ('paramvalue');}}, Extend: event: event});4. Демо -инструкции
Продемонстрировать структуру кода:
То, что подготовлено, является соответствующей частью демонстрации. html/regist.html - это страница, которая демонстрирует эффект, а JS/app/regist.js - это запись в демонстрационный эффект JS:
Определите (function (require, exports, module) {var $ = require ('jquery'); var cascadeview = require ('mod/cascadeview'); function publicsetcascadeview (fieldname, opts) {this.cascadeview = new Cascadeview ({$ elements: $ ('## + fieldname +'). '../api/cascade.json', onchanged: this.onchanged, значения: opts.values, gotionfirstoption: this.keepfirstoption, resolveajax: function (res) {if (res.code == 200) {return res.data; $ ('input [name = "LicenseLocation"]'), KeepFirstoption: true, setCascadeView: publicsetCascadeView, onchanged: function (e, value) {location_views.licenseLocation. $ input.val (значение); SetCascadeView: publicsetcascadeview, onchanged: function (e, value) {location_views.companylocation. $ input.val (value); Location_views.companylocation.setcascadeview ('companyLocation', {values: location_views.companylocation. $ Input.val ()});});Обратите внимание на функцию переменной location_views в приведенном выше коде, потому что на странице существует несколько каскадных компонентов. Эта переменная фактически управляется аналогичным образом через модель политики. Если вы этого не делаете, легко генерировать дублированный код; Эта форма также более способствует разделению и инкапсуляции какой -то бизнес -логики в файле входа, такой как место, где обрабатывается бизнес -логика.
5. Другие
Это, вероятно, последний блог, написанный компанией сейчас. Вы должны пойти на работу в новом подразделении через два дня. Я не уверен, что у вас так много свободного времени для записи ваших обычных рабочих идей, но, по крайней мере, вы разработали привычку писать блоги, и вы выпустите время, если у вас не будет времени в будущем. Цель в этом году состоит в том, чтобы расширить знания и улучшить качество кода. Последующие блоги будут больше в категории разработки компонентов. Я надеюсь, что вы сможете продолжать обращать внимание на веб -сайт wulin.com в будущем!