предисловие
Расположение каталога:
Применение шаблонов проектирования в Vue (1)
Применение шаблонов проектирования в Vue (2)
Применение шаблонов проектирования в Vue (3)
Применение шаблонов проектирования в Vue (4)
Применение шаблонов проектирования в Vue (5)
Применение шаблонов проектирования в Vue (6)
Применение шаблонов проектирования в Vue (7)
Зачем писать эти статьи. так какШаблон проектирования — это набор повторяющихся, наиболее известных, классифицированных сводок опыта проектирования кода.(из энциклопедии Baidu), я также хочу обсудить со всеми прелесть шаблонов проектирования, поделившись некоторыми накопленными в моей работе.
Сценарии приложений, представленные в этой серии статей, чтобы помочь в объяснении, являются реальными сценариями приложений в действии, конечно, они не могут охватывать все аспекты, но они также охватывают общие бизнес-сценарии по аналогии.
Главным героем сегодняшнего дня должен стать шаблон проектирования, который мы чаще всего используем при разработке фреймворков (таких как: vue, react) — шаблон метода шаблона.
Определение (из сети):
Шаблон Template Method определяет скелет алгоритма в методе и откладывает реализацию некоторых шагов до подклассов. Шаблонные методы позволяют подклассам переопределять конкретную реализацию определенных шагов в алгоритме без изменения структуры алгоритма.
1. Реализация ООП
1. Скелет алгоритма
Алгоритм строения тела животного имеет: голова, туловище, ноги
// template class
// 注意:JavaScript里面没有接口的概念,与传统的OOP实现有一定的缺陷
class AnimalTemplate {
constructor() {}
head () {}
body () {}
foot () {}
render () {
// 算法过程 ———— 身体部位排列顺序头、身体、脚
// render方法不能被子类重写,无法通过JavaScript本身实现需人为遵守
this.head()
this.body()
this.foot()
}
}
2. Реализация алгоритма подкласса
// 有一头猪
class Pig extends AnimalTemplate {
head () {
console.log('head from pig')
}
body () {
console.log('body from pig')
}
foot () {
console.log('foot from pig')
}
}
const pig1 = new Pig()
pig1.render() // 执行算法
// 有一只鸡
class Chicken extends AnimalTemplate {
head () {
console.log('head from chicken')
}
body () {
console.log('body from chicken')
}
foot () {
console.log('foot from chicken')
}
}
const chicken1 = new Chicken()
chicken1.render() // 执行算法
2. Реагировать на реализацию
Нет проблем с компонентами класса в реакции с использованием вышеприведенной реализации ООП, но способ наследования, похоже, не очень популярен в реакции, и более популярным является функциональное программирование (передача реквизита)
1. Приходите на очень распространенную сцену
class Parent {
constructor() {}
render () {
<div>
<div name="tom"></div>
<!-- 算法过程:children要渲染在name为joe的div中 -->
<div name="joe">{this.props.children}</div>
</div>
}
}
class Stage {
constructor() {}
render () {
// 在parent中已经设定了children的渲染位置算法
<Parent>
// children的具体实现
<div>child</div>
</Parent>
}
}
Таким образом, мы уже используем шаблон метода шаблона, когда пишем jax.
2. Повторно реализовать пример, выполненный в ООП
// 算法模板
class AnimalTemplate {
constructor() {
...
}
render () {
// 算法过程————头、身体、脚的顺序
return (
<div>
{this.props.renderHead()}
{this.props.renderBody()}
{this.props.renderFoot()}
</div>
)
}
}
// 具体需求
class Stage {
constructor() {}
pigRenderHead () {
return <div>pig head</div>
}
pigRenderBody () {
return <div>pig body</div>
}
pigRenderFoot () {
return <div>pig foot</div>
}
chickenRenderHead () {
...
}
chickenRenderBody () {
...
}
chickenRenderFoot () {
...
}
render () {
<div>
<AnimalTemplate
renderHead={this.pigRenderHead}
renderBody={this.pigRenderBody}
renderFoot={this.pigRenderFoot}
/>
<AnimalTemplate
renderHead={this.chickenRenderHead}
renderBody={this.chickenRenderBody}
renderFoot={this.chickenRenderFoot}
/>
</div>
}
}
Суммировать
В этом разделе я считаю, что у всех есть более четкое представление о свойствах рендеринга реакции.
3. Реализация Vue
После выполнения двух вышеуказанных шагов относительно просто понять применение шаблона метода шаблона в Vue.
1, дети находятся в div с именем joe
// parent.vue
<template>
<div>
<div name="tom"></div>
<div name="joe">
<!--vue中的插槽渲染children-->
<slot />
</div>
</div>
</template>
// stage.vue
<template>
<div>
<parent>
<!-- children的具体实现 -->
<div>child</div>
</parent>
</div>
</template>
2. Повторно реализовать пример, выполненный в ООП
// AnimalTemplate.vue
<template>
<div>
<slot name="head"></slot>
<slot name="body"></slot>
<slot name="foot"></slot>
</div>
</template>
// stage.vue
<template>
<div>
<animal-template>
<div slot="head">pig head</div>
<div slot="body">pig body</div>
<div slot="foot">pig foot</div>
</animal-template>
<animal-template>
<div slot="head">chicken head</div>
<div slot="body">chicken body</div>
<div slot="foot">chicken foot</div>
</animal-template>
</div>
</template>
Суммировать
От реализации ООП до реализации реакции, а затем получения реализации vue, теперь каждый должен иметь возможность легко понять, как применяется шаблон метода шаблона в vue.
В-четвертых, сделайте что-нибудь
Благодаря приведенному выше введению мы должны были освоить теоретические знания шаблона шаблонного метода и должны применить их, если у нас есть новые навыки.
Сцены:
Отображение списка должно быть обычной операцией. Независимо от того, что это за список, он будет иметь следующие характеристики: отображать состояние загрузки при запросе данных, выдавать подсказку при отсутствии данных и отображать список при наличии данных.
1. Инкапсуляция алгоритма
Согласно теории паттерна шаблонного метода, нам сначала нужно инкапсулировать алгоритм рендеринга списка:
- Запрос данных --> загрузка
- данные пусты --> подсказка о пустых данных
- Получить данные --> список рендеринга
// renderList.vue
<template>
<div>
<img v-if="isLoading" src="./loading.gif" />
<div v-if="isEmpty">数据为空</div>
<div v-else>
<div v-for="(item, index) in data" :key="index">
<!-- vue中的作用域插槽 -->
<slot name="item" :data="item" />
</div>
</div>
</div>
</template>
<script>
export default {
name: 'RenderList',
props: {
isLoading: Boolean,
data: Array,
},
computed: {
isEmpty () {
return this.data.length < 1
}
}
}
</script>
2. Определите выполнение определенных шагов (элементы списка)
// stage.vue
<template>
<div>
<render-list :isLoading="isStudentsLoding" :data="students">
<!-- 学生信息的渲染 -->
<div slot="item" slot-scope="{ data }">
<div>名字:{{ data.name }}</div>
<div>年龄:{{ data.age }}</div>
</div>
</render-list>
<render-list :isLoading="isFamilyLoading" :data="family">
<!-- 家庭成员的渲染 -->
<div slot="item" slot-scope="{ data }">
<!-- 不同的DOM结构 -->
<div>
<span>称呼:{{ data.role }}</span>
名字:{{ data.name }}
</div>
</div>
</render-list>
</div>
</template>
<script>
import RenderList form './renderList'
export default {
data () {
return {
isStudentsLoding: false,
isFamilyLoading: false,
students: [
{ name: 'aa', age: '18' },
{ name: 'bb', age: '19' },
{ name: 'cc', age: '120' }
],
family: [
{ name: 'aaaa', role: '爸爸' },
{ name: 'bbbb', role: '妈妈' },
{ name: 'cccc', role: '本人' },
]
}
},
components: {
RenderList
}
}
</script>
3. Более сложный
При рендеринге списка учеников выше я хочу отобразить оценки по каждому предмету учеников.Структура данных выглядит следующим образом:
export default {
...
data () {
return {
students: [
{ name: '小明',
age: 16,
score: [
{ course: '语文', value: 86 },
{ course: '数学', value: 88 }
]
},
{ name: '小李',
age: 16,
score: [
{ course: '语文', value: 90 },
{ course: '数学', value: 85 }
]
}
]
}
}
...
}
Реализовано вручную у детей?
<render-list :isLoading="isStudentsLoding" :data="students">
<div slot="item" slot-scope="{ data }">
<div>名字:{{ data.name }}</div>
<div>年龄:{{ data.age }}</div>
<!-- 我们能拿到每个学生的信息,手动渲染成绩列表 -->
<div v-for="score in data.score" :key="score.course">
<slot name="score" :data="score" />
</div>
</div>
</render-list>
Корректировка нашего алгоритма списка
Вышеупомянутый метод может достичь нашей цели, но рендеринг списка слишком важен для пользователя, и нам нужно настроить наш шаблон алгоритма.
// renderList.vue
<template>
<div>
<img v-if="isLoading" src="./loading.gif" />
<div v-if="isEmpty">数据为空</div>
<div v-else>
<div v-for="(item, index) in source" :key="index">
<!-- 学生信息 -->
<slot name="item" :data="item"></slot>
<!-- 学生分数 -->
<div class="score">
<div v-for="score in item.score" :key="score.course">
<slot name="score" :data="score" />
</div>
</div>
</div>
</div>
</div>
</template>
// stage.vue
<template>
<div>
<render-list :isLoading="isStudentsLoding" :data="students">
<!-- 学生信息渲染规则 -->
<div slot="item" slot-scope="{ data }">
<div>名字:{{ data.name }}</div>
<div>年龄:{{ data.age }}</div>
</div>
<!-- 学生成绩渲染规则 -->
<div slot="score" slot-scope="{ data }">
<div>——课程:{{ data.course }}</div>
<div>——成绩:{{ data.value }}</div>
</div>
</render-list>
</div>
</template>
Суммировать
В этой статье в основном рассматривается концепция режима разработки слота в vue и показано применение режима метода шаблона в сочетании со сценой рендеринга списка.
Я видел, как кто-то в Интернете использовал различные хитрые операции для реализации vue's render props.Теперь посмотрим, нужно ли это.Как ни посмотри на слот, он больше радует глаз (API слота немного беспокоил, когда я написал эту статью, v2.6.0 очень хорошее решение этой проблемы)
为什么开头说模板方法模式是vue、react开发中使用最多的设计模式?
通过上面的介绍相信大家已经感受到模板方法模式的特点:
1,封装一个算法模板
2,用户负责某一步的具体实现
现在想想vue,react内部封装好了diff算法、状态改变触发更新的机制、生命周期,我们在使用框架时只
需要按照语法规则使用它们的API完成我们的业务逻辑,这也就是模板方法模式
Реализация этой статьи также применима к реакции, почему в статье в качестве вопроса используется vue? Шаблон Vue может заставить нас чувствовать себя немного неловко при понимании некоторых концепций, а jsx реакции можно рассматривать как написание JavaScript, чтобы быть более гибким для реализации различных концепций.
Дружеское напоминание: о применении шаблонов проектирования в Vue следует написать серию, и учащиеся, которым это нравится, не забудьте обратить внимание