Это первый день моего участия в Gengwen Challenge, смотрите подробности мероприятия:Обновить вызов
предисловие
Эта статья и все последующие статьи из серии об упаковке компонентов основаны наelement-uiБиблиотека компонентов инкапсулирована, и API element-ui в ней обсуждаться не будет.В этой статье будут обсуждаться некоторые технические мысли о функции рендеринга в инкапсуляции компонентов и может использоваться для производственных проектов, поэтому Vue3 не используется, и это будет медленно инкапсулироваться позже Компонент интеграции общей формы в середине и на заднем плане, эта статья начинается с поля ввода,
поддерживаемые типы
- text
- input
- number
- password
- textarea
Input Attributes
| параметр | иллюстрировать | Типы | По умолчанию |
|---|---|---|---|
| value / v-model | значение привязки | [String, Number] |
'' |
| type | тип формы | ["input", "text", "number", "password", "email", "textarea"] |
text |
| Поддержка всех параметров el-input |
dynamic-input
<script>
// 供全局使用
let h
// 支持的类型(只做输入框,radio/checkbox另外拆开)
const selectInputType = [
'input',
'text',
'number',
'password',
'email',
'textarea'
]
export default {
name: 'DynamicInput',
// attrs不显示在dom上
inheritAttrs: false,
props: {
// 类型
type: {
default: 'text',
validator: typeVal => {
return selectInputType.includes(typeVal)
}
},
// 绑定值
value: {
type: [String, Number],
default: ''
},
// 支持el-input所有参数
},
computed: {
newValue: {
get({ value }) {
return value
},
set(val) {
this.$emit('input', val)
}
},
},
methods: {
onInputHandle(val) {
this.newValue = val
}
},
render() {
h = this.$createElement
const {
onInputHandle,
$attrs,
} = this
return h('el-input', {
props: {
type: this.type,
value: this.newValue,
...this.$attrs
},
on: {
input: onInputHandle,
},
})
}
}
</script>
Навыки, которые вы можете получить
- Двусторонняя привязка с помощью вычисляемого
- пройти через
$attrsДля осуществления прозрачной передачи параметров можно не указыватьpropПараметры, которые не нужно передавать
поговорим об этом здесьinheritAttrs, этот параметр указывает, следует ли монтировать данные, определенные в $attrs, на уровень dom, прямо над
Модификаторы, поддерживаемые формой
- номер: пропуск
parseFloat()Строковое значение после разбора - обрезка: фильтрация начальных и конечных пробельных символов
- ленивый: изменить триггер события от ввода, чтобы реагировать после подтверждения значения «аналогично изменению» (это можно использовать без изменения значения, когда метод ввода не нажат)
Наиболее распространенным является случай, когда мы используем поле ввода числового типа, но последнее заданное значение поля ввода является строкой.В это время мы можем добавить.numberМодификатор автоматически преобразует его в числовой тип для вас
<dynamic-input
v-model="testVal"
type="number"
/>
<!-- testVal => 'string' -->
<dynamic-input
v-model.number="testVal"
type="number"
/>
<!-- testVal => 'number' -->
"Эффект ленивого модификатора"
Input Events
служба поддержкиel-inputвсе события
<template>
<dynamic-input
ref="dynamicInput"
v-model.lazy="testVal"
:type="testType"
:class="computedClass"
@change="changeMethod"
@input.native="inputMethod"
/>
</template>
<script>
import dynamicInput from '@/components/common/dynamic-input'
export default {
name: 'CkTestInput',
components: {
'dynamic-input': dynamicInput
},
data() {
return {
testType: 'text',
testVal: '',
restaurants: []
}
},
computed: {
computedClass({ testVal }) {
return { 'is-fill': testVal }
}
},
methods: {
changeTestVal(changeVal) {
this.testVal = changeVal
},
inputMethod(val) {
console.log(val, '-->')
},
changeMethod(val) {
console.log(val, '-->')
},
}
}
</script>
Также поддерживает собственные события модификатора
Input Methods
служба поддержкиel-inputНа все методы должна быть ссылка refdynamic-inputкомпонент, упакованныйel-inputимя по умолчаниюelInput
<template>
<dynamic-input
ref="dynamicInput
value="test"
/>
</template>
<script>
export default {
mounted() {
// 可以获取到dynamicInput组件内封装的elInput组件
this.$refs.dynamicInput.$refs.elInput
}
}
</script>
Вы также можете переименовать значение ref внутреннего компонента elInput, определив refName
<template>
<dynamic-input
ref="dynamicInput"
refName="child-input'
value="test"
/>
</template>
<script>
export default {
mounted() {
// 可以获取到dynamicInput组件内封装的elInput组件
this.$refs.dynamicInput.$refs['child-input']
const {
dynamicInput
} = this.$refs
// 可以通过去调用el-input组件提供方法
dynamicInput.$refs['child-input'].focus()
}
}
</script>
Нам просто нужно добавить эту строку суждения в функцию рендеринга
<script>
export default {
render() {
let {
$attrs
} = this
return h('el-input', {
// ...
ref: $attrs['ref-name'] || 'elInput'
})
}
}
</script>
Input Slots
поддерживать всехel-inputПредусмотрены встроенные слоты
<template>
<dynamic-input
ref="dynamicInput"
refName="child-input'
value="test"
>
<template slot="prepend">Http://</template>
<i slot="prefix" class="el-input__icon el-icon-search" />
<i slot="suffix" class="el-input__icon el-icon-date" />
</dynamic-input>
</template>
Нужно обратить внимание на парсинг слота.В официальном документе нет списка слотов для функции рендеринга.Также очень неясно как это реализовать.Следует отметить что третий параметр в функции рендера описывает текущий Подсодержимое, хотя слот является встроенным содержимым, предоставляемым текущим компонентом, позволяющим выполнять рендеринг в указанное содержимое текущего компонента, но это не так.
<script>
export default {
render() {
h = this.$createElement
return h('el-input', {
// ....
}, Object.values(this.$slots))
}
}
</script>
Окончательный результат третьего параметра здесь => [VNode, VNode], но обратите внимание, что VNode неУкажите имя слота
Документация была взята здесь только поверхностноДетализация объектов данных 👉
Поэтому при рендеринге содержимого встроенного слота, предоставленного el-input, нам нужно определить объект данных, который предоставляет имя слота для рендеринга VNode.Здесь мы используем функциональный компонент без состояния, чтобы делать что-то
slotContent.js
// 用于处理插槽
export default {
name: 'SlotContent',
// 声明这是一个函数式组件
functional: true,
props: {
render: {
type: Function,
require: true
},
data: Object
},
render: (h, ctx) => {
// 函数式组件中没有this, 所有可用的API都提供在ctx中
return ctx.props.render(h, ctx.props.data)
}
}
Для некоторых компонентов, которые не выполняют никакой обработки состояния, вы можете использовать функциональные компоненты для создания относительно «легких» компонентов.Подробности смотрите в описании документа 👉
<script>
// 渲染el-input提供的slot
function renderElInputSlots($scopedSlots) {
const slots = Object.keys($scopedSlots).map(slotName => {
return h('slot-content', {
props: {
render: $scopedSlots[slotName]
},
slot: slotName,
key: slotName
})
})
return slots
}
export default {
render() {
h = this.$createElement
const {
$scopedSlots,
} = this
// 配置插槽(当用户传递了el-input提供的slot才去渲染)
let elInputSlotsVNode = []
if (Object.keys($scopedSlots).length) {
elInputSlotsVNode = renderElInputSlots($scopedSlots)
}
return h('el-input', {
// ...
}, elInputSlotsVNode)
}
}
</script>
«Эффекты 💗»
Autocomplete
автозаполнение — это компонент поля ввода с предложениями ввода. Можно использовать для удаленного поиска, передавis-autocompleteопределить, следует ли рендеритьel-autocompleteкомпоненты
Примечание⚠: is-autocomplete здесь используется, чтобы определить, следует ли отображать компонент el-autocomplete, а не атрибут автозаполнения, предоставленный вводом.
| параметр | иллюстрировать | Типы | По умолчанию |
|---|---|---|---|
is-autocomplete |
Отображать ли как компонент автозаполнения | Boolean |
false |
fetch-suggestions |
返回输入建议的方法,仅当你的输入建议数据 resolve 时,通过调用 callback(data:[]) 来返回它 |
Function |
должен пройти |
Подробную информацию можно найти на официальном сайте Element-Ui.элемент. Вы голодны. Можете ли вы/#/this-cn/com…
<script>
export default {
props: {
// 是否渲染el-autocomplete组件
isAutocomplete: {
type: Boolean,
default: false
}
// 支持el-input所有参数
},
computed: {
// 最终要渲染的组件名称
componentTag: {
get({ isAutocomplete, $attrs }) {
const fetchSuggestions = $attrs['fetch-suggestions']
// fetchSuggestions 返回输入建议的方法(isAutocomplete为true时必传)
return isAutocomplete && typeof fetchSuggestions === 'function'
? 'el-autocomplete'
: 'el-input'
}
}
},
render() {
h = this.$createElement
const {
componentTag
} = this
return h(componentTag, {
// ...
}, elInputSlotsVNode)
}
}
</script>
Приведенная выше реализация аналогична действию встроенного динамического компонента [component] component
На данный момент этот компонент написан, и всего около 100 строк, но он относительно гибкий и будет упакован позже.FormКомпонент будет интегрировать этот компонент, и в настоящее время он может хорошо отражать гибкость функции рендеринга для инкапсуляции компонента.
Онлайн скромный, если вы считаете, что эта статья полезна для вас, пожалуйста, поставьте лайк 👻
напиши в конце
Если есть часть статьи, которая написана не очень хорошо или имеет проблемы, вы можете указать на нее, и я продолжу исправлять ее в следующих статьях. Я также надеюсь, что смогу расти вместе с вами по мере моего прогресса. Друзья, которым нравятся мои статьи, также могут обратить внимание
Я был бы признателен, если бы первым подписался на меня.В это время молодые я и ты шли в бой налегке, потом богатые ты и я возвращались с полным грузом.
В игре пренебрегают усердием
Прошлые статьи
[Рекомендуется продолжить] Создавайте промежуточные и конечные проекты с модульными идеями.
[Разработка мидл- и бэкенд-проектов с модульными идеями] Глава 1
[Внешняя система] Расскажите о понимании EventLoop из вопроса на собеседовании.(Обновлен анализ четырех дополнительных вопросов)
[Фронтальная система] Построить многоэтажку с фундамента
[Фронтальная система] Сценарий приложения регулярного в разработке — это не просто проверка правил