【IMWeb训练营作业】之select组件
第二个作业,用Vue完成select组件。
Vue中的组件:
Vue中组件是一个自定义标签,也可以扩展原生的HTML元素,封装可重用的代码。
组件的特性:
- 高内聚性;
- 低耦合性;
- 每个组件都有自己清晰的职责,完整的功能,较低的耦合性,便于单元测试和重复利用。
组件的基本构成:
- 样式结构
- 行为逻辑
- 数据
此次作业涉及的技术要点:
(1)Vue.component:注册组件(全局注册),也可直接在Vue实例中注册,即局部注册;
(2)template:组件的HTML结构;
(3)props:声明在组件中需要显示的自定义属性名;
(4)父子组件之间的通信:父组件用v-on(@)绑定自定义事件,用来监听子组件的事件;子组件用$emit触发父组件所关心的事件,同时将值传给父组件;
(5)HTML元素的扩展:有些元素中不能直接使用自定义标签,可用html元素的is属性来扩展,例如:<tr is="custom"></tr>;
(6)组件的数据要以函数的形式传入
作业代码:
HTML:
<body>
<div id="app">
<!--btn-value和v-bind:绑定数据-->
<custom-select btn-value="查询" v-bind:list="list1"></custom-select>
<div is="custom-select" btn-value="搜索" v-bind:list="list2"></div>
<!--用html元素的is属性扩展-->
</div>
<script src="index.js"></script>
</body>
CSS:
* {
padding: 0;
margin: 0;
list-style: none;
box-sizing: border-box;
font-size: 20px;
}
.select-con {
width: 445px;
margin: 50px;
background: url(bg.png);
padding: 40px 20px;
border-radius: 10px;
}
.con {
width: 400px;
background: #f3f3f3;
border-radius: 25px;
padding: 5px;
position: relative;
}
.keyword {
width: 300px;
height: 40px;
border: 1px solid lightgray;
background: lightgray;
border-radius: 20px;
outline: 0;
text-indent: 2rem;
}
.btn {
width: 82px;
height: 40px;
background: aquamarine;
outline: 0;
border: 0;
border-radius: 20px;
float: right;
}
.icon-sousuo-sousuo {
position: absolute;
color: white;
font-size: 28px;
top: 10px;
left: 10px;
}
.option-con {
padding: 2px 10px;
}
.option-con li {
margin-top: 7px;
padding: 5px 15px;
border-radius: 25px;
}
.option-con li:hover {
background: lightpink;
}
JavaScript:
Vue.component("custom-select", {//注册组件,父组件
data: function() {
return {
show: false,
val: ""
};
}, //data以函数形式传入
props: ["btnValue", "list"], //传递数据
template: `<div class="select-con">
<div class="con">
<input class="keyword" type="text" :value="val">
<!--动态绑定val-->
<!--绑定自定义值;点击show取反-->
<i class="icon iconfont icon-sousuo-sousuo"></i>
<custom-option v-show="show" :list="list" @receive="changeValueHandle"></custom-option>
<!--show控制option的显示和隐藏-->
<!--@recieve绑定自定义事件,用来监听子组件的事件是否被触发,触发了就执行change方法-->
</div>
</div>`,
methods: {
changeValueHandle: function(value) {// change方法改变input的值
this.val = value;
}
}
}
Vue.component("custom-option", {// 子组件
props: ["list"], //从父组件传来的数据
template: `<ul class="option-con">
<li v-for="item of list" @click="selectValueHandle(item)">{{item}}</li>
</ul>`,
methods: {
selectValueHandle: function(item) { // 在子组件中有交互,告知父组件,val的值有变化,需要一个自定义事件
this.$emit("receive", item);// 如果触发了,就把item传给父组件,同时触发父组件的自定义receive事件
}
}
})
new Vue({
el: "#app",
data: {
list1: ["北京", "上海", "天津", "深圳", "大连"],
list2: ["HTML", "CSS", "JS", "PHP", "JAVA", "IOS", "LESS", "SASS"]
}
})