Если понимать первый шаг в разработке компонентов vue, то, несомненно, это то, как достигается связь между родительским и дочерним компонентами (проще говоря, именно так передаются данные в родительском и дочернем компонентах), только Понимая этот шаг, можно улучшить компоненты разработки
Вот два ключевых слова:propsа такжеemit:
Перед написанием этого компонента посмотрите на рендеринг:
Анализ разработки компонентов:
Так как это компонент:
- Прежде всего, содержимое внутренних данных компонента должно быть переменным (например, «сортировать по времени» на приведенном выше рисунке), которое должно передаваться родительским компонентом (то есть, как родительский компонент передает данные родительскому компоненту). компонент);
- После выбора содержимого, как передать данные (то есть, как дочерний компонент передает данные родительскому компоненту)
Сначала напишите структуру:
родительский компонент
<!--下拉框父组件-->
<template>
<div id="app">
<oSelect @changeOption="onChangeOption" :selectData="selectData"></oSelect>
<!--
selectData: 传入父组件需要传入的数据;格式:childDataName="parentDataName";
onChangeOption: 子组件触发的事件名,通过触发一个事件从而来接收子组件的传过来的数据
格式:@childEventName="parentEventName"
注:可写多个
-->
</div>
</template>
<script>
import oSelect from "@/components/select.vue"; //引入组件
export default{
name: 'App',
data(){
return {
selectData: {
defaultIndex: 0, //默认选中的是第几个
selectStatus: false, // 通过selectStatus来控制下拉框的显示/隐藏
selectOptions: [ // 下拉框中的数据 name这样的参数,看项目是否有需求,可自行修改
{
name: 'time',
context: '按时间排序'
},
{
name: 'view',
context: '按浏览量排序'
},
{
name: 'like',
context: '按点赞数排序'
},
{
name: 'reply',
context: '按回复数排序'
},
{
name: 'reward',
context: '按打赏数排序'
}
]
}
}
},
methods:{
onChangeOption(index){
//子组件通过一个事件来触发onChangeOption方法,从而传递一系列参数,这里的index就是传过来的
this.selectData.defaultIndex = index;
//触发过后,动态改变了需要值
}
},
components: {
oSelect,
//注册组件
}
}
</script>
Подсборка
<template>
<!-- 下拉框组件html结构(子组件) -->
<div class="select-box" @click="changeStatus">
<!-- changeStatus事件: 点击实现下拉框的显示和隐藏 -->
<h3 class="select-title"
:name="selectData.selectOptions[selectData.defaultIndex].name"
:class="{'select-title-active': selectData.selectStatus}">
<!--属性name class的动态绑定-->
{{ selectData.selectOptions[selectData.defaultIndex].context }}
<!--这里主要绑定选择的数据-->
</h3>
<transition name="slide-down">
<!--transition 实现下拉列表显示隐藏时的动画-->
<ul class="select-options" v-show="selectData.selectStatus">
<li class="select-option-item"
v-for="(item,index) in selectData.selectOptions"
@click="EmitchangeOption(index)"
:class="{'select-option-active':selectData.defaultIndex===index}">
<!--
v-for:循环数据渲染下拉列表
EmitchangeOption:点击下拉列表事件
class:动态绑定被选中的数据
-->
{{ selectData.selectOptions[index].context }}
</li>
<div class="arrow-top"></div>
</ul>
</transition>
</div>
</template>
<script>
export default{
name: 'oSelect', //建议大家都写上这个,有利于我们知道这个组件叫什么名字
//通过props来接收父组件传过来的数据
props:{
selectData: {
type: Object //规定传过来的数据为对象,否则就会报错(其实这样写就是规避错误和良好的习惯)
}
},
methods:{
EmitchangeOption(index){
this.$emit('changeOption',index);
// 通过点击事件触发EmitchangeOption函数,传入当前点击下拉列表中的索引值index
// 下拉框通过emit方法触发父组件中changeOption函数,动态传给父组件需要的数据,这里为索引值
},
changeStatus(){
// 通过changeStatus事件动态改变selectStatus的值,从而控制下拉框的显示隐藏
this.selectData.selectStatus = !this.selectData.selectStatus
}
}
}
</script>
Суммировать
- Как видно из приведенного выше примера, когда родительский компонент передает данные, необходимо привязать свойство в родительском компоненте для монтирования данных, которые необходимо передать;
- Дочерний компонент получает данные от родительского компонента черезpropsспособ получения;
- Подкомпоненты для передачи данных необходимо использоватьemitметод для привязки предварительно установленного метода в родительском компоненте, чтобы динамически передавать данные, необходимые после операции
Окончательный эффект выглядит следующим образом:
Прикрепите css к компоненту только для справки:
.select-box{
position: relative;
max-width: 250px;
line-height: 35px;
margin: 50px auto;
}
.select-title{
position: relative;
padding: 0 30px 0 10px;
border: 1px solid #d8dce5;
border-radius: 5px;
transition-duration: 300ms;
cursor: pointer;
}
.select-title:after{
content: '';
position: absolute;
height: 0;
width: 0;
border-top: 6px solid #d8dce5;
border-left: 6px solid transparent;
border-right: 6px solid transparent;
right: 9px;
top: 0;
bottom: 0;
margin: auto;
transition-duration: 300ms;
transition-timing-function: ease-in-out;
}
.select-title-active{
border-color: #409eff;
}
.select-title-active:after{
transform: rotate(-180deg);
border-top-color: #409eff;
}
.select-options{
position: absolute;
padding:10px 0;
top: 45px;
border:1px solid #d8dce5;
width: 100%;
border-radius: 5px;
}
.select-option-item{
padding:0 10px;
cursor: pointer;
transition-duration: 300ms;
}
.select-option-item:hover,.select-option-active{
background: #f1f1f1;
color: #409eff;
}
<!--箭头css-->
.arrow-top{
position: absolute;
height: 0;
width: 0;
top: -7px;
border-bottom: 7px solid #d8dce5;
border-left: 7px solid transparent;
border-right: 7px solid transparent;
left: 0;
right: 0;
margin: auto;
z-index: 99;
}
.arrow-top:after{
content: '';
position: absolute;
display: block;
height: 0;
width: 0;
border-bottom: 6px solid #fff;
border-left: 6px solid transparent;
border-right: 6px solid transparent;
left: -6px;
top: 1px;
z-index: 99;
}
<!--下拉框显示隐藏动画-->
.slide-down-enter-active,.slide-down-leave{
transition: all .3s ease-in-out;
transform-origin:0 top;
transform: scaleY(1);
}
.slide-down-enter{
transform: scaleY(0);
}
.slide-down-leave-active{
transition: all .3s ease-in-out;
transform-origin:0 top;
transform: scaleY(0);
}
Хорошо, эта статья окончена. Спасибо за чтение. Если что-то не так, пожалуйста, поправьте меня. Большое спасибо. Если вы хотите узнать больше о интерфейсе,Пожалуйста, найдите и подпишитесь на общедоступную учетную запись WeChat【большой интерфейс js】, узнайте больше о передовых аппаратных технологиях
Оригинальность непростая, просьба указывать источник при перепечатке.