前言
最近在学习vue,今天看到自定义组件,纠结了一会会然后恍然大悟...官方教程写得不是很详细,所以我决定总结一下。下面话不多说了,来一起看看详细的介绍吧。
效果
先让我们看一下例子的效果吧!
我们知道 v-model 是 vue 里面的一个指令,vue的v-model是一个十分强大的指令,它可以自动让原生表单组件的值自动和你选择的值绑定,它可以用在 input 标签上,来做数据的双向绑定,就像这样:
<input v-model="tab">
v-model 事实上是一个语法糖,你也可以这么写:
<input :value="tab" :input="tab = $event.target.value">
可以看得出来,就是传进去一个参数 :value,监听一个事件 @input 而已。
如果有这样的需求,需要在自己的组件上使用 v-model,就像这样:
<Tab v-model="tab"></Tab>
如何来实现呢?
既然已经知道 v-model 是语法糖了,那么首先,我们可以知道在组件内得到的参数。
<!-- Tab.vue --> <template> <div class="tab"> <p>可以试着把这个值打印出来"htmlcode"><!-- example.vue --> <template> <div> <!-- 这里多了一个参数 ↓ --> <Tab v-model="tab" :options="options"></Tab> <p class="info">{{tab}}</p> </div> </template> <script> import Tab from '~/Tab'; export default { components: { Tab }, data() { return { tab: 'bj', options: [{ value: 'bj', text: '北京' }, { value: 'sh', text: '上海', disabled: true }, { value: 'gz', text: '广州' }, { value: 'sz', text: '深圳' }] } } } </script>那我们就把传进来的 options 循环出来吧!
<!-- Tab.vue --> <template> <div class="tab"> <div class="item" v-for="(item, i) in options" :key="i"> {{item.text}} </div> </div> </template> <script> export default { props: { value: { type: String }, options: { type: Array, default: [] } } } </script>传进来的 options 缺少些参数,我们每个选项需要 active 来标记是否是选中状态,需要 disabled 来标记是否是禁选状态,所以拷贝一个 currOptions 来补全不足参数。
另外直接改变 value 这个 props 是没有效果滴,所以拷贝一个 value 的副本,叫 currValue。
<!-- Tab.vue --> <script> export default { props: { value: { type: String }, options: { type: Array, default: [] } }, data() { return { // 拷贝一个 value currValue: this.value, currOptions: [] } }, mounted() { this.initOptions(); }, methods: { initOptions() { // 拷贝一个 options this.currOptions = this.options.map(item => { return { ...item, active: item.value === this.currValue, disabled: !!item.disabled } }); } } } </script>"htmlcode">
<!-- Tab.vue --> <template> <div class="tab"> <div class="item" v-for="(item, i) in options" :key="i" @click="onTabSelect(item)"> <!-- ↑ 这里绑定了一个事件! --> {{item.text}} </div> </div> </template> <script> export default { props: { value: { type: String }, options: { type: Array, default: [] } }, data() { return { currValue: this.value, currOptions: [] } }, mounted() { this.initOptions(); }, methods: { initOptions() { this.currOptions = this.options.map(item => { return { ...item, active: item.value === this.currValue, disabled: !!item.disabled } }); }, // 添加选中事件 onTabSelect(item) { if (item.disabled) return; this.currOptions.forEach(obj => obj.active = false); item.active = true; this.currValue = item.value; // 发布 input 事件,↓ 父组件如果有 v-model 就会监听到的。 this.$emit('input', this.currValue); } } } </script>剩下的补上点样式还有 watch 下 value 和 options 的变化就可以了,最后贴上完整代码。
完整代码
<!-- example.vue --> <template> <div> <Tab v-model="tab" :options="options"></Tab> <p class="info">{{tab}}</p> </div> </template> <script> import Tab from '~/Tab'; export default { components: { Tab }, data() { return { tab: 'bj', options: [{ value: 'bj', text: '北京' }, { value: 'sh', text: '上海', disabled: true }, { value: 'gz', text: '广州' }, { value: 'sz', text: '深圳' }] } } } </script> <style lang="less" scoped> .info { margin-left: 50px; font-size: 30px; } </style><!-- Tab.vue --> <template> <div class="tab"> <div class="item" v-for="(item, i) in currOptions" :class="item | tabItemClass" :key="i" @click="onTabSelect(item)"> {{item.text}} </div> </div> </template> <script> export default { props: { value: { type: String }, options: { type: Array, default: [] } }, data() { return { currValue: this.value, currOptions: [] } }, mounted() { this.initOptions(); }, methods: { initOptions() { this.currOptions = this.options.map(item => { return { ...item, active: item.value === this.currValue, disabled: !!item.disabled } }); }, onTabSelect(item) { if (item.disabled) return; this.currOptions.forEach(obj => obj.active = false); item.active = true; this.currValue = item.value; this.$emit('input', this.currValue); } }, filters: { tabItemClass(item) { let classList = []; if (item.active) classList.push('active'); if (item.disabled) classList.push('disabled'); return classList.join(' '); } }, watch: { options(value) { this.initOptions(); }, value(value) { this.currValue = value; } } } </script> <style lang="less" scoped> .tab { @borderColor: #ddd; @radius: 5px; width: 100%; margin: 50px; overflow: hidden; position: relative; .item { padding: 10px 50px; border-top: 1px solid @borderColor; border-left: 1px solid @borderColor; border-bottom: 1px solid @borderColor; font-size: 30px; background-color: #fff; float: left; user-select: none; cursor: pointer; transition: 300ms; &:first-child { border-top-left-radius: @radius; border-bottom-left-radius: @radius; } &:last-child { border-right: 1px solid @borderColor; border-top-right-radius: @radius; border-bottom-right-radius: @radius; } &.active { color: #fff; background-color: red; } &:hover { color: #fff; background-color: #f06; } &.disabled { color: #fff; background-color: pink; cursor: no-drop; } } } </style>最后送上官网的链接→ 传送门
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对的支持。
免责声明:本站资源来自互联网收集,仅供用于学习和交流,请遵循相关法律法规,本站一切资源不代表本站立场,如有侵权、后门、不妥请联系本站删除!
P70系列延期,华为新旗舰将在下月发布
3月20日消息,近期博主@数码闲聊站 透露,原定三月份发布的华为新旗舰P70系列延期发布,预计4月份上市。
而博主@定焦数码 爆料,华为的P70系列在定位上已经超过了Mate60,成为了重要的旗舰系列之一。它肩负着重返影像领域顶尖的使命。那么这次P70会带来哪些令人惊艳的创新呢?
根据目前爆料的消息来看,华为P70系列将推出三个版本,其中P70和P70 Pro采用了三角形的摄像头模组设计,而P70 Art则采用了与上一代P60 Art相似的不规则形状设计。这样的外观是否好看见仁见智,但辨识度绝对拉满。
更新日志
- 凤飞飞《我们的主题曲》飞跃制作[正版原抓WAV+CUE]
- 刘嘉亮《亮情歌2》[WAV+CUE][1G]
- 红馆40·谭咏麟《歌者恋歌浓情30年演唱会》3CD[低速原抓WAV+CUE][1.8G]
- 刘纬武《睡眠宝宝竖琴童谣 吉卜力工作室 白噪音安抚》[320K/MP3][193.25MB]
- 【轻音乐】曼托凡尼乐团《精选辑》2CD.1998[FLAC+CUE整轨]
- 邝美云《心中有爱》1989年香港DMIJP版1MTO东芝首版[WAV+CUE]
- 群星《情叹-发烧女声DSD》天籁女声发烧碟[WAV+CUE]
- 刘纬武《睡眠宝宝竖琴童谣 吉卜力工作室 白噪音安抚》[FLAC/分轨][748.03MB]
- 理想混蛋《Origin Sessions》[320K/MP3][37.47MB]
- 公馆青少年《我其实一点都不酷》[320K/MP3][78.78MB]
- 群星《情叹-发烧男声DSD》最值得珍藏的完美男声[WAV+CUE]
- 群星《国韵飘香·贵妃醉酒HQCD黑胶王》2CD[WAV]
- 卫兰《DAUGHTER》【低速原抓WAV+CUE】
- 公馆青少年《我其实一点都不酷》[FLAC/分轨][398.22MB]
- ZWEI《迟暮的花 (Explicit)》[320K/MP3][57.16MB]