前言
这是我参与8月更文挑战的第7天,活动详情查看:8月更文挑战。恰逢掘金
八月更文挑战,想必很多初学Vue的小伙伴经常看到一个英文单词component,不知道如何写组件以及理解slot插槽概念的时候犯头痛,在跟着敲完代码之后,心里可能想过组件和插槽居然可以这么配合使用,极大降低了代码的耦合度,轻轻松松实现代码的复用,太啊眉紧了吧!废话少叙,今天希望能够通过这个小案例帮助到大家。加油,共勉!
页面效果展示
需求分析
首先,进入到用户管理列表,就获取用户注册的所有信息数据,并通过数据表格动态渲染出来,每一个用户独占一行,并且根据用户 id 号给定固定的序号。
其次,表格的最后一列作为操作列,通过按下删除按钮,根据用户 id 后台删除该用户信息以及其他的绑定的数据,删除完毕后,dom 结构随之发生变化,实现自动渲染表格,序号 -- ,指定的行消失,到此彻底完成删除操作。
最后,为了更好的用户操作体验,及时反馈点击删除按钮之后删除操作结果,倘若用户误操作,可点击取消按钮,取消这次删除操作。此外,删除操作完成之后,询问一次用户是否返回主菜单页面。
代码实现
[v-cloak] {
display: none;
}
这里为什么使用v-cloak 指令设置样式呢?
由于打开页面时就开始动态加载数据表格,当网络较慢或者加载的数据较多时,网页还在加载 Vue.js ,而导致 Vue 来不及渲染,这时页面就会显示出 Vue 源代码 ,比如经常使用到的 {{}} 。我们可以使用v-cloak 指令来解决屏幕闪动这一问题。
另外,这些样式会在 Vue 实例编译结束时,从绑定的 HTML 元素上被移除。
在简单项目中,使用 v-cloak 指令是解决屏幕闪动的好方法。但是在大型、工程化的项目中(webpack、vue-router)只有一个空的 div 元素,元素中的内容是通过路由挂载来实现的,而不使用 v-cloak 指令。
<body>
<div id="usersTable" v-cloak>
<my-table id="my-table">
<my-thead slot="my-thead"></my-thead>
<my-tbody slot="my-tbody" v-for="(user, index) in users" v-bind:user="user" v-bind:index="index" v-bind:key="index" v-on:remove="delUser(index)"></my-tbody>
</my-table>
</div>
</body>
注意:
要为每个组件提供一个 key ,尽管不影响,但是会出现警告信息(要有显式的键):warning:component lists rendered with v-for should have explicit keys 。
Q:那为什么要为组件提供一个 key ?
- 为了给 Vue 一个提示,以便它能
跟踪每个节点的身份 - 从而重用和重新排序现有元素,你需要为每项提供一个
唯一 key属性
// myTable 中设置插槽
Vue.component('myTable', {
template:
'<table>\
<slot name="my-thead"></slot >\
<slot name="my-tbody"></slot>\
</table>'
});
// 表格头 插槽
Vue.component('myThead', {
props: ['user'],
template:
'<tr>\
<th>序号</th>\
<th>uid</th>\
<th>用户名</th>\
<th>姓名</th>\
<th>性别</th>\
<th>生日</th>\
<th>年龄</th>\
<th>手机号码</th>\
<th>密码</th>\
<th>是否删除</th>\
</tr>\
'
});
// 表格体 插槽
Vue.component('myTbody', {
props: ['index','user'],
template:
'<tr>\
<td>{{index}}</td>\
<td>{{user.uid}}</td>\
<td>{{user.username}}</td>\
<td>{{user.name}}</td>\
<td v-if="user.gender">男</td>\
<td v-else>女</td>\
<td>{{user.birthday}}</td>\
<td>{{user.age}}</td>\
<td>{{user.mobile}}</td>\
<td>{{user.password}}</td>\
<td><button id="tableBut" v-on:click="remove">删除</button></td>\
</tr>\
',
methods: {
remove: function (object) {
// 组件内部绑定事件
this.$emit('remove', object);
}
}
});
注意: 定义组件名的时候要使用单引号或者双引号括起来,否则怀疑人生!
prop 属性
prop 属性:类似于一个自定义 attribute 属性且和 HTML 一样大小写不敏感。
props中的变量名不能以短横线分割命名法命名,否则无法进行数据绑定。props中的变量名要么全小写要么以驼峰命名法进行命名。- 相应地,驼峰命名时,
v-bind绑定的属性名以短横线命名法进行命名(推荐都小写);全小写时,就对应写就完事了。
组件名命名【避坑】
组件名以及注册组件(注册组件尽量全使用小写字母):
- 当组件名以短横线分割命名时,不允许出现大写,限制都为小写
- 注册组件时也要使用同名标签不能更改大小写
- 当组件名以单驼峰命名法命名时,例如:
myComcamelCase(驼峰命名法) 的prop名需要使用其等价的kebab-case(短横线分隔命名) 命名进行注册组件- 例如:
my-com、my-Com等不限制大小写,但是标签尽量全使用小写
- 例如:
- 当组件名出现双驼峰时,例如:
MyCom- 也是可以使用其等价的
kebab-case(短横线分隔命名) 命名进行注册组件(例如:使用my-com)- 注意:
- 在 2、3 两种情况下都不能使用同名或者不区分大小写同名注册组件
- 必须使用等价的命名,否则报错:
did you register the component correctly? For recursive components, make sure to provide the "name" option.
- 注意:
- 也是可以使用其等价的
- 当组件名出现n驼峰时,例如:
MyCoM、MyCoMpOnEnT...- 都要遵循短横线分割命名法进行注册组件(例如:
my-co-m,my-co-mp-on-en-t...)
- 都要遵循短横线分割命名法进行注册组件(例如:
- 当组件命名不遵循短横线命名法和驼峰命名法时(出现两个以上字母连续大写或者全小写),例如:
MYcom、MyCOm、MYCOM、mycom...- 只有全小写的情况下,组件才能注册成功,不会报错
Vue 核心代码
var vm = new Vue({
el: '#usersTable',
data: {
users: []
},
created: function () {
$.ajax({
type: 'POST',
url: '/user/getAllUsersInfo',
success: function (data) {
initUsersInfo(data);
},
error: function (error) {
alert(error)
}
});
},
methods: {
delUser: function (index) {
// 当前序号
var num = index.valueOf();
var uid = this.users[num].uid;
var ans = confirm(`确认要删除 uid => ${uid} 的用户吗?`);
if(ans === true) {
this.users.splice(index, 1);
$.ajax({
type: 'POST',
url: '/user/delUserByUid',
data: {
uid: uid
},
success: function (data) {
alert(data.msg);
var ifExit = confirm('是否返回主菜单页面?');
if(ifExit) {
window.location.href = '../index.html';
}
},
error: function (error) {
alert(error)
}
});
}else {
alert('你取消了删除操作!');
}
}
}
});
function initUsersInfo(data) {
if(jQuery.isEmptyObject(data)) {
alert("用户表中空空如也~")
}else {
vm.users = data;
}
}
首先,Vue 数据定义部分,定义了一个存放用户信息的数组,使用vue.js 中 created 方法,它是一个生命周期钩子函数,当一个vue实例被生成后会调用这个函数,这个函数的具体功能就是调用后端接口,获取 tb_user 表下所有用户数据,然后实现数据的双向绑定。
其次,就是根据我们之前说过的需求一步一步实现了,要删除用户的 id 是通过组件内部 this.$emit 绑定事件(事件名自定义),但是仅此并不足够,这并不能帮我们完成想要的功能,仅是传递参数的工具方法罢了,真正删除方法是是定义在 Vue 实例的 methods 中的,通过传递 index 序号,this.users[num].uid 通过序号下标拿到用户 id 。
到此,小案例就此实现了,如果对 component 组件、slot 插槽还抱有疑问的,请移步 Vue.js官网,自行查阅。
结尾
撰文不易,欢迎大家点赞、评论,你的关注、点赞是我坚持的不懈动力,感谢大家能够看到这里!Peace & Love。