【Vue.JS】Vue.JS 标签组件实例

版权声明:本文为博主原创文章,转载请注明出处。 https://blog.csdn.net/shaotaiban1097/article/details/90719200

声明:文中代码来源于 梁灏 编著的 【Vue.JS 实战】一书,并非原创。
学习过程中因觉得该组件效果不错,比较实用,所以自己记录以下供以后学习。

效果图

img

代码

  • HTML
<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8">
    <title>标签组件</title>
    <link rel="stylesheet" type="text/css" href="style.css">
</head>

<body>

    <div id="app" v-cloak>
        <tabs v-model="activeKey">
            <pane label="标签一" name="1">
                标签一的内容
            </pane>
            <pane label="标签二" name="2">
                标签二的内容
            </pane>
            <pane label="标签三" name="3">
                标签三的内容
            </pane>
        </tabs>

    </div>

    <script src="https://cdn.bootcss.com/vue/2.6.10/vue.js"></script>
    <script src="pane.js"></script>
    <script src="tabs.js"></script>
    <script>
        var app = new Vue({
            el: '#app',
            data: {
                activeKey: '1'
            }
        })
    </script>
</body>

</html>
  • pane.js
Vue.component('pane', {
	template: '\
      <div class="pane" v-show="show">\
        <slot></slot>\
      </div>\
        ',
	name: "pane",
	data: function () {
		return {
			show: true
		};
	},
	props: {
		name: {
			type: String
		},
		label: {
			type: String,
			default: ""
		}
	},
	methods: {
		updateNav() {
			this.$parent.updateNav();
		}
	},
	watch: {
		label() {
			this.updateNav();
		}
	},
	mounted() {
		this.updateNav();
	}
})
  • tabs.js
Vue.component('tabs', {
	name: "tabs",
	template: '\
		<div class="tabs">\
			<div class="tabs-bar">\
				<!-- 标签列表遍历 -->\
						<div\
							:class="tabCls(item)"\
							v-for="(item, index) in navList"\
							:key="item.id"\
							@click="handleChange(index)"\
						>{{item.label}}</div>\
			</div>\
			<div class="tabs-content">\
				<!-- slot 嵌套 pane -->\
				<slot></slot>\
			</div>\
		</div>\
	',
	data() {
		return {
			navList: [],
			currentValue: this.value //复制一份value自己维护,value 是为了可以使用 v-model
		};
	},
	props: {
		value: {
			type: [String, Number]
		}
	},
	methods: {
		getTabs() {
			return this.$children.filter(function (item) {
				return item.$options.name === "pane";
			});
		},
		updateNav() {
			this.navList = [];
			this.getTabs().forEach((pane, index) => {
				this.navList.push({
					label: pane.label,
					name: pane.name || index
				});
				if (!pane.name) panem.name = index;
				if (index == 0)
					if (!this.currentValue) _this.currentValue = pane.name || index;
			});
			this.updateStatus();
		},
		updateStatus() {
			var tabs = this.getTabs();
			tabs.forEach(tab => {
				return (tab.show = tab.name === this.currentValue);
			});
		},

		tabCls: function (item) {
			return [
				"tabs-tab",
				{
					"tabs-tab-active": item.name === this.currentValue
				}
			];
		},
		handleChange: function (index) {
			var nav = this.navList[index];
			var name = nav.name;
			this.currentValue = name;
			this.$emit('input', name);
			this.$emit('on-click', name);
		}
	},
	watch: {
		value: function (val) {
			this.currentValue = val;
		},
		currentValue: function () {
			this.updateStatus();
		}
	},
})
  • style.css
.tabs {
    font-size: 14px;
    color: '#657180';
}

/* IE8 只支持单冒号 */
.tabs-bar::after {
    content: '';
    display: block;
    width: 100px;
    height: 1px;
    background-color: #d7dde4;
    margin-top: -1px;
}

.tabs-tab {
    display: inline-block;
    padding: 4px 16px;
    margin-right: 6px;
    background-color: #ffffff;
    border: 1px solid #d7dde4;
    cursor: pointer;
    position: relative;
}

.tabs-tab-active {
    color: #3399FF;
    border-top: 1px solid #3399ff;
    border-bottom: 1px solid #ffffff;
}

/* IE8 只支持单冒号 */
.tabs-tab-active::before {
    content: '';
    display: block;
    height: 1px;
    background-color: #3399ff;
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
}

.tabs-content {
    padding: 8px 0;
}

猜你喜欢

转载自blog.csdn.net/shaotaiban1097/article/details/90719200