В ежедневном процессе разработки проекта процесс инкапсуляции компонентов часто неотделим. Например, у страницы а есть функция, которая используется страницами b и c. В это время мы рассматриваемповторное использование кода, рассмотрит возможность сделать эту функцию компонентом. В этой статье мы поговорим о некоторых разработках компонентов vue.Советыи немного черного(Сан)разделение(Держать) технология (делать).
Мы объясним один за другим на большом количестве примеров
содержание
- Общие советы по компонентам функций
- функциональные компоненты
- встроенный шаблон
-
рекурсивный компонент
-
v-onceСтатическая составляющая с низкими накладными расходами - компонент вызова глобальной функции
Общие советы по компонентам функций
Во-первых, мы используем скаффолдинг для создания проекта для написания наших компонентов.Iview. Написание функциональных компонентов неотделимо от взаимодействия между компонентами通信, Есть много статей по теме, в этой статье не буду подробно останавливаться, вот рекомендация о Наггетсахкомпонент связиСтатья написана очень подробно и заинтересованные друзья могут зайти и посмотреть.
слот слот
Слоты слотов должны иметь высокую скорость использования, когда мы обычно пишем компоненты. Буду<slot>Элементы действуют как выходы для доставки контента, и мы можем включать любой код шаблона в слоты, что делает наши компоненты более гибкими. Давайте поговорим о более классическом примере диалогового компонента, сначала взглянем на код.
<template>
<div>
<div>头部</div>
<div>
<slot>默认内容</slot>
</div>
<div>
<slot name="footer"> <Button>确认</Button> </slot>
</div>
</div>
</template>
<script>
export default { name: "model" };
</script>
На этикетке модели, за исключением слотаfooterКод, остальные коды будут отображаться как основное содержимое диалогового окна, это作用域插槽Применение. пока слотfooterКод будет отображаться в разделе кнопки действия внизу, соответствующем<slot name="footer">Это具名插槽Применение.
прозрачная передача атрибута
Сценариев прозрачной передачи атрибутов не так много, возьмем в качестве примера вторичную инкапсуляцию компонентов пользовательского интерфейса. Если вы часто используете UI-компонент в своем проекте, и этому UI-компоненту нужно каждый раз задавать много похожих свойств, то мы можем провести вторичную инкапсуляцию, которую удобнее вызывать, а можно даже расширить функцию на оригинале компонент. Давайте посмотрим на фрагмент кода, который дважды инкапсулирует компонент таблицы Iview.
<script>
import { Table } from "iview";
export default {
name: "customizeTable",
props: { ...Table.props, test: { type: [String], default: "扩展属性" } },
data() {
return { defaultProps: { border: true, stripe: true } };
},
render(h) {
var props = Object.assign({ ...this._props }, this.defaultProps);
return h(Table, { props: props });
}
};
</script>
// Способ второй
<template>
<div>
<Table v-bind="{...mergeProps}"></Table>
</div>
</template>
<script>
import { Table } from "iview";
export default {
name: "customizeTable",
props: {
...Table.props,
test: {
type: [String],
default: "扩展属性"
}
},
computed: {
mergeProps: function() {
return Object.assign({ ...this._props }, this.defaultProps);
}
},
data() {
return {
defaultProps: {
border: true,
stripe: true
}
};
}
};
</script>
Сначала получаем все дефолтные параметры Таблицы через свойство props компонента Таблицы, а затем передаемthis._propsРеализуйте прозрачную передачу свойств, а также мы можем расширить нужные вам свойства в реквизитах, напримерtest. В методе 1 мы используем метод рендеринга для привязки свойств, которые мы подробно рассмотрим в функциональных компонентах. Во втором методе мы используем v-bind для привязки всех свойств объекта.
функциональные компоненты
Давайте сначала процитируем введение официального сайта в функциональные компоненты.
Функциональный компонент не управляет никаким состоянием, не прослушивает переданное ему состояние и не имеет методов жизненного цикла. На самом деле это просто функция, которая принимает некоторые реквизиты. В таком случае мы можем пометить компонент какfunctional, что означает, что он не имеет состояния (нетотзывчивые данные), и нет экземпляра (нетthisконтекст).
Все, что нужно компоненту, передаетсяcontextПередача параметров, это объект со следующими полями:
-
props: объект, предоставляющий все реквизиты -
children: массив дочерних узлов VNode -
slots: функция, которая возвращает объект, содержащий все слоты -
scopedSlots: (2.6.0+) Объект, раскрывающий переданный слот с областью действия. Также предоставляет обычные слоты как функции. -
data: все значение передается компонентуобъект данных, так какcreateElementВторой параметр входящего компонента -
parent: ссылка на родительский компонент -
listeners: (2.3.0+) Объект, содержащий все прослушиватели событий, зарегистрированные родительским компонентом для текущего компонента. Этоdata.onпсевдоним . -
injections: (2.3.0+) если используетсяinjectвариант, объект содержит свойства, которые должны быть внедрены.
в добавленииfunctional: trueПосле этого нам нужно обновить функцию рендеринга нашего компонента анкорного заголовка, чтобы добавитьcontextпараметры и будетthis.$slots.defaultобновить доcontext.children,Потомthis.levelобновить доcontext.props.level.
Зачем использовать функциональные компоненты?
Поскольку функциональные компоненты не имеют жизненного цикла, состояния и экземпляров, это означает, что они быстрее отображаются и имеют меньшие накладные расходы, а поскольку функциональные компоненты — это просто функции, мы можем реализовать некоторую логику, которая нам нужна, в функциях.
Когда использовать функциональные компоненты?
На мой взгляд, функциональные компоненты больше похожи на роль промежуточного программного обеспечения, поэтому их более распространенный сценарий приложения — это компонент-оболочка. Например, у нас есть компонент, который может отображать один из нескольких компонентов, и нам нужно решить, какой компонент отображать в соответствии с переданными параметрами.Давайте посмотрим на фрагмент кода.
export default {
functional: true,
render: function (createElement, context) {
return createElement(context.props.domType, context.data, context.children);
}
}
<template>
<div>
<functionnalScript domType="model" style="width:100%"></functionnalScript>
</div>
</template>
<script>
import customizeTable from "../components/customizeTable.vue";
import model from "../components/model.vue";
import functionnalScript from "../components/functionnal.js";
export default {
name: "pageA",
components: {
customizeTable,
model,
functionnalScript: functionnalScript
}
};
</script>
<template functional>
<div>
<button v-bind="data.attrs" v-on="listeners">
<slot />
</button>
</div>
</template>
Когда родительская страница вызывается нормально, у нас есть компонент customTable и компонент модели, которые мы можем передать в свойствеdomTypeУкажите functionnalScript для отображения соответствующего компонента, и его можно повторно использовать в нескольких местах.
Помните, что мы говорили ранее?属性透传, на самом деле прозрачная передача атрибутов может быть достигнута и через функциональные компоненты.Давайте посмотрим на функциональный компонент шаблона.Функциональный компонент реализует полную прозрачную передачу любогоattribute,事件监听器,子节点Ждать.
встроенный шаблон
Шаблон компонента обычно определяется в параметре шаблона, и когда встроенный шаблон использует компонент, используйте функцию встроенного шаблона для тега компонента, и компонент будет обрабатывать свое содержимое как шаблон, а не распространять его как содержимое. Сделайте шаблоны более гибкими. Но это также вызвало некоторые проблемы, давайте сначала посмотрим на код.
<script>
export default {
name: "inlineChildren",
data() {
return { tip: "我是子组件的数据" };
}
};
</script>
<template>
<div>
<inlineChildren inline-template>
<div>
<h3>{{tip}}</h3>
</div>
</inlineChildren>
</div>
</template>
<script>
import inlineChildren from "../components/inlineChildren.vue";
export default {
name: "pageA",
components: { inlineChildren },
data() {
return { tip: "我是父组件的数据" };
}
};
</script>
Существование встроенного шаблона делает содержимое внутри тега inlineChildren больше не слотом (содержимое дистрибутива), а компонентом inlineChildren.template, а контекст, в котором находится эта часть содержимого, является дочерним, а не родительским компонентом. Так что, если нет специальной сцены (я никогда с ней не сталкивался~~), другая подходящая, как сказано на официальном сайте,inline-templateУсложняет понимание объема шаблонов. Поэтому в качестве наилучшей практики, пожалуйста, предпочтите внутри компонентаtemplateвариант или.vueодин из файлов<template>элемент для определения шаблона.
рекурсивный компонент
Что такое рекурсивный компонент?
Вызов самого себя в собственном шаблоне компонента — это то, что мы называем рекурсивным компонентом. (Обратите внимание, что вам нужно передатьnameпередача)
Каковы сценарии использования?
В нашей повседневной разработке еще много места для рекурсивных компонентов, например, наши меню, комментарии и другие иерархические функции. Рассмотрим пример меню:
<template>
<div>
<div v-for="item in menuList">
<div class="hasChildren">{{item.name}}
<Icon v-if="item.children" type="ios-arrow-down" />
</div>
<side-menu v-if="item.children" :menuList="item.children"></side-menu>
</div>
</div>
</template>
<script>
export default {
name: "SideMenu",
props: {
menuList: {
type: Array,
default() {
return [];
}
}
}
};
</script>
<style>
.hasChildren {
background: #999;
color: #fff;
height: 40px;
line-height: 40px;
}
</style>
<template>
<div>
<sideMenu :menuList="menuList"></sideMenu>
</div>
</template>
<script>
import sideMenu from "../components//side-menu.vue";
export default {
name: "pageA",
components: { sideMenu },
data() {
return {
menuList: [
{ name: "side1", children: [{ name: "side1-1" }, { name: "side1-2" }] },
{
name: "side2",
children: [
{ name: "side2-1" },
{ name: "side2-2", children: [{ name: "side2-2-1" }] }
]
}
]
};
}
};
</script>
Мы видим, что внутри вызывается сам компонент sideMenu, так в основном используются рекурсивные компоненты. В более сложной ситуации есть два компонента А и В, и между ними существует вызывающая связь. Тогда возникает вопрос, что первично, курица или яйцо.
Модульная система обнаруживает, что ей нужен А, но сначала А зависит от В, который, в свою очередь, зависит от А, который, в свою очередь, зависит от В, и так далее. Это становится циклом, не знаю, как полностью разобрать другой, не просматривая один из компонентов, есть 2 обходных пути.
//方法一 在A组件
beforeCreate: function () {
this.$options.components.TreeFolderContents = require('./B.vue').default
}
//方法二 异步加载B组件
components: {
B: () => import('./B.vue')
}
Статические компоненты v-once с низкими накладными расходами
Если ваш компонент появляетсямногостатический контент, то они могут замедлить рендеринг вашего компонента, в этом случае вы можете добавить корневой элементv-onceатрибут, чтобы гарантировать, что они вычисляются только один раз, а затем кэшируются.
<template>
<div v-once> {{hugeData}} </div>
</template>
<script>
export default {
name: "vOnce",
data() {
return { hugeData: "huge Data..." };
},
mounted() {
setTimeout(() => {
this.hugeData = "change Data...";
}, 100);
}
};
</script>
ты найдешьhugeDataЭто всегда были огромные данные... не изменились, потому чтоv-onceВ результате данные изменяются после рендеринга шаблона и не могут нормально обновляться, поэтому, учитывая, что другие разработчики не обязательно понимают этот атрибут, старайтесь не использовать его без особой необходимости.
компонент вызова глобальной функции
Обычный процесс вызова компонента:
<testModule></testModule>
import TestModule from "./TestModule "
export default { components: { testModule }};
Если вам нужно использовать этот компонент в нескольких местах, это означает, что вам нужно повторять описанные выше шаги каждый раз, когда вы его вызываете.Есть ли более удобный способ вызвать его?console.log,alertНе странно, иногда мы также хотим иметь возможность вызывать компонент таким образом, вместо того, чтобы записывать компонент в узел. Например, компоненту окна подсказки может потребоваться разбудить его в разное время и предложить соответствующее содержимое.Мы реализуем этот компонент подсказки с помощью кода.
//extend.js
import Vue from 'vue'import Tip from './tip.vue';
//使用基础 Vue 构造器,创建一个包含tip组件的“子类”
Tip.newInstance = (props) => {
const tip = Vue.extend(Tip);
const messageInstance = new tip({ propsData: props });
const div = document.createElement('div');
document.body.appendChild(div); messageInstance.$mount(div)
}
export default Tip.newInstance
//main.js
import tip from 'extend.js'Vue.prototype.$tip=tip;
//调用
this.$tip({});
Таким образом, мы можем добиться этого, вызвав функциюthis.$tip({})Назовем компонент Tip. Как видите, наша основная идея состоит в том, чтобы создать экземпляр vue, содержащий нужные нам компоненты, а затем смонтировать этот экземпляр во вновь созданный div. Если мы можем вызвать эту функцию несколько раз, на страницу будет добавлено несколько элементов div, а это не то, что нам нужно, поэтому мы можем оптимизировать ее снова.
<template>
<div>
<div v-for="item in tips">
<tip v-bind="item"></tip>
</div>
</div>
</template>
<script>
let i = 0;
const now = new Date().getTime();
function getUid() {
return "tip" + now + "-" + i++;
}
import tip from "./tip.vue";
export default {
name: "tipList",
data() {
return { tips: [] };
},
components: { tip },
methods: {
add(options) {
let name = getUid;
let _options = Object.assign({ name: name }, options);
this.tips.push(_options);
}
}
};
</script>
import Vue from 'vue'import Tip from './tipList.vue';
let tip, initialization;
//使用基础 Vue 构造器,创建一个包含tip组件的“子类”
Tip.newInstance = () => {
tip = Vue.extend(Tip);
const messageInstance = new tip();
const div = document.createElement('div');
document.body.appendChild(div);
messageInstance.$mount(div)
return {
prompt(props) {
messageInstance.add(props);
}
}
}
initialization=function(){
if(!tip){
tip=Tip.newInstance()
}
return tip
}
export default initialization
//main.js
import tip from 'extend.js'
Vue.prototype.$tip=tip;
//调用
this.$tip.prompt({});
Мы передаем компонентtipList.vueизpromptМетод реализует требования компонента подсказки, который вызывается несколько раз Каждый раз, когда вызывается компонент подсказки, это эквивалентно помещению объекта в массив подсказок, который отрисовывает еще один компонент подсказки.
Суммировать
Я надеюсь, что после прочтения вы также сможете использовать их в своих компонентах, чтобы ваши компоненты могли уменьшить некоторую ненужную логику. У автора могут быть некоторые недоразумения. Я надеюсь, что большой парень сможет выразить это в комментариях, и мы сможем учиться и добиваться прогресса вместе.
Другие порталы статей:
-
Реализация больших таблиц данных на веб-стороне на основе vue
- Карта Baidu - обновление больших точек данных в режиме реального времени