论企业网站建设的必要性,网站建设设计制,如何通过建设一个网站赚钱,花店网站建设方案零、文章目录
Vue2基础八、插槽
1、插槽
#xff08;1#xff09;默认插槽
作用#xff1a;让组件内部的一些 结构 支持 自定义需求: 将需要多次显示的对话框, 封装成一个组件问题#xff1a;组件的内容部分#xff0c;不希望写死#xff0c;希望能使用的时候自定义。…零、文章目录
Vue2基础八、插槽
1、插槽
1默认插槽
作用让组件内部的一些 结构 支持 自定义需求: 将需要多次显示的对话框, 封装成一个组件问题组件的内容部分不希望写死希望能使用的时候自定义。怎么办 插槽基本语法 组件内需要定制的结构部分改用slot/slot占位使用组件时, MyDialog/MyDialog标签内部, 传入结构替换slot 代码实现 父组件App.vue templatediv!-- 2. 在使用组件时组件标签内填入内容 --MyDialogdiv你确认要删除么/div/MyDialogMyDialogp你确认要退出么/p/MyDialog/div
/templatescript
import MyDialog from ./components/MyDialog.vue
export default {data () {return {}},components: {MyDialog}
}
/scriptstyle
body {background-color: #b3b3b3;
}
/style子组件MyDialog.vue templatediv classdialogdiv classdialog-headerh3友情提示/h3span classclose✖️/span/divdiv classdialog-content!-- 1. 在需要定制的位置使用slot占位 --slot/slot/divdiv classdialog-footerbutton取消/buttonbutton确认/button/div/div
/templatescript
export default {data () {return {}}
}
/scriptstyle scoped
* {margin: 0;padding: 0;
}
.dialog {width: 470px;height: 230px;padding: 0 25px;background-color: #ffffff;margin: 40px auto;border-radius: 5px;
}
.dialog-header {height: 70px;line-height: 70px;font-size: 20px;border-bottom: 1px solid #ccc;position: relative;
}
.dialog-header .close {position: absolute;right: 0px;top: 0px;cursor: pointer;
}
.dialog-content {height: 80px;font-size: 18px;padding: 15px 0;
}
.dialog-footer {display: flex;justify-content: flex-end;
}
.dialog-footer button {width: 65px;height: 35px;background-color: #ffffff;border: 1px solid #e1e3e9;cursor: pointer;outline: none;margin-left: 10px;border-radius: 3px;
}
.dialog-footer button:last-child {background-color: #007acc;color: #fff;
}
/style2后备内容默认值
通过插槽完成了内容的定制传什么显示什么, 但是如果不传则是空白能否给插槽设置 默认显示内容 呢 插槽后备内容封装组件时可以为预留的 slot 插槽提供后备内容默认内容。 语法: 在 slot 标签内放置内容作为默认内容slot后备内容/slot 外部使用组件时不传东西则slot会显示后备内容 MyDialog/MyDialog外部使用组件时传东西了则slot整体会被换掉 MyDialog我是内容/MyDialog代码实现 父组件App.vue templatedivMyDialog/MyDialogMyDialog你确认要退出么/MyDialog/div
/templatescript
import MyDialog from ./components/MyDialog.vue
export default {data () {return {}},components: {MyDialog}
}
/scriptstyle
body {background-color: #b3b3b3;
}
/style子组件MyDialog.vue templatediv classdialogdiv classdialog-headerh3友情提示/h3span classclose✖️/span/divdiv classdialog-content!-- 往slot标签内部编写内容可以作为后备内容(默认值) --slot我是默认的文本内容/slot/divdiv classdialog-footerbutton取消/buttonbutton确认/button/div/div
/templatescript
export default {data () {return {}}
}
/scriptstyle scoped
* {margin: 0;padding: 0;
}
.dialog {width: 470px;height: 230px;padding: 0 25px;background-color: #ffffff;margin: 40px auto;border-radius: 5px;
}
.dialog-header {height: 70px;line-height: 70px;font-size: 20px;border-bottom: 1px solid #ccc;position: relative;
}
.dialog-header .close {position: absolute;right: 0px;top: 0px;cursor: pointer;
}
.dialog-content {height: 80px;font-size: 18px;padding: 15px 0;
}
.dialog-footer {display: flex;justify-content: flex-end;
}
.dialog-footer button {width: 65px;height: 35px;background-color: #ffffff;border: 1px solid #e1e3e9;cursor: pointer;outline: none;margin-left: 10px;border-radius: 3px;
}
.dialog-footer button:last-child {background-color: #007acc;color: #fff;
}
/style3具名插槽
需求一个组件内有多处结构需要外部传入标签进行定制默认插槽一个的定制位置 具名插槽语法: 多个slot使用name属性区分名字template配合v-slot:名字来分发对应标签v-slot:插槽名 可以简化成 #插槽名 代码实现 父组件App.vue templatedivMyDialog!-- 需要通过template标签包裹需要分发的结构包成一个整体 --template v-slot:headdiv我是大标题/div/templatetemplate v-slot:contentdiv我是内容/div/templatetemplate #footerbutton取消/buttonbutton确认/button/template/MyDialog/div
/templatescript
import MyDialog from ./components/MyDialog.vue
export default {data () {return {}},components: {MyDialog}
}
/scriptstyle
body {background-color: #b3b3b3;
}
/style子组件MyDialog.vue templatediv classdialogdiv classdialog-header!-- 一旦插槽起了名字就是具名插槽只支持定向分发 --slot namehead/slot/divdiv classdialog-contentslot namecontent/slot/divdiv classdialog-footerslot namefooter/slot/div/div
/templatescript
export default {data () {return {}}
}
/scriptstyle scoped
* {margin: 0;padding: 0;
}
.dialog {width: 470px;height: 230px;padding: 0 25px;background-color: #ffffff;margin: 40px auto;border-radius: 5px;
}
.dialog-header {height: 70px;line-height: 70px;font-size: 20px;border-bottom: 1px solid #ccc;position: relative;
}
.dialog-header .close {position: absolute;right: 0px;top: 0px;cursor: pointer;
}
.dialog-content {height: 80px;font-size: 18px;padding: 15px 0;
}
.dialog-footer {display: flex;justify-content: flex-end;
}
.dialog-footer button {width: 65px;height: 35px;background-color: #ffffff;border: 1px solid #e1e3e9;cursor: pointer;outline: none;margin-left: 10px;border-radius: 3px;
}
.dialog-footer button:last-child {background-color: #007acc;color: #fff;
}
/style4作用域插槽 作用域插槽: 定义 slot 插槽的同时, 是可以传值的。给 插槽 上可以 绑定数据将来 使用组件时可以用。 场景封装表格组件 父传子动态渲染表格内容利用默认插槽定制操作列删除或查看都需要用到 当前项的 id属于 组件内部的数据通过 作用域插槽 传值绑定进而使用 基本使用步骤 给 slot 标签, 以 添加属性的方式传值 slot :iditem.id msg测试文本/slot所有添加的属性, 都会被收集到一个对象中 { id: 3, msg: 测试文本 }在template中, 通过 #插槽名 obj 接收默认插槽名为 default MyTable :listlisttemplate #defaultobjbutton clickdel(obj.id)删除/button/template
/MyTable代码实现 父组件App.vue templatedivMyTable :datalist!-- 3. 通过template #插槽名变量名 接收 --template #defaultobjbutton clickdel(obj.row.id)删除/button/template/MyTableMyTable :datalist2template #default{ row }button clickshow(row)查看/button/template/MyTable/div
/templatescript
import MyTable from ./components/MyTable.vue
export default {data () {return {list: [{ id: 1, name: 张小花, age: 18 },{ id: 2, name: 孙大明, age: 19 },{ id: 3, name: 刘德忠, age: 17 },],list2: [{ id: 1, name: 赵小云, age: 18 },{ id: 2, name: 刘蓓蓓, age: 19 },{ id: 3, name: 姜肖泰, age: 17 },]}},methods: {del (id) {this.list this.list.filter(item item.id ! id)},show (row) {// console.log(row);alert(姓名${row.name}; 年纪${row.age})}},components: {MyTable}
}
/script子组件MyTable.vue templatetable classmy-tabletheadtrth序号/thth姓名/thth年纪/thth操作/th/tr/theadtbodytr v-for(item, index) in data :keyitem.idtd{{ index 1 }}/tdtd{{ item.name }}/tdtd{{ item.age }}/tdtd!-- 1. 给slot标签添加属性的方式传值 --slot :rowitem msg测试文本/slot!-- 2. 将所有的属性添加到一个对象中 --!-- {row: { id: 2, name: 孙大明, age: 19 },msg: 测试文本}--/td/tr/tbody/table
/templatescript
export default {props: {data: Array}
}
/scriptstyle scoped
.my-table {width: 450px;text-align: center;border: 1px solid #ccc;font-size: 24px;margin: 30px auto;
}
.my-table thead {background-color: #1f74ff;color: #fff;
}
.my-table thead th {font-weight: normal;
}
.my-table thead tr {line-height: 40px;
}
.my-table th,
.my-table td {border-bottom: 1px solid #ccc;border-right: 1px solid #ccc;
}
.my-table td:last-child {border-right: none;
}
.my-table tr:last-child td {border-bottom: none;
}
.my-table button {width: 65px;height: 35px;font-size: 18px;border: 1px solid #ccc;outline: none;border-radius: 3px;cursor: pointer;background-color: #ffffff;margin-left: 5px;
}
/style2、综合案例-商品列表
1功能需求
my-tag 标签组件封装 (1) 双击显示输入框输入框获取焦点(2) 失去焦点隐藏输入框(3) 回显标签信息(4) 内容修改回车 → 修改标签信息 my-table 表格组件封装 (1) 动态传递表格数据渲染(2) 表头支持用户自定义(3) 主体支持用户自定义 2代码实现
父组件App.vue
templatediv classtable-caseMyTable :datagoodstemplate #headth编号/thth名称/thth图片/thth width100px标签/th/templatetemplate #body{ item, index }td{{ index 1 }}/tdtd{{ item.name }}/tdtdimg:srcitem.picture//tdtdMyTag v-modelitem.tag/MyTag/td/template/MyTable/div
/templatescript
// my-tag 标签组件的封装
// 1. 创建组件 - 初始化
// 2. 实现功能
// (1) 双击显示并且自动聚焦
// v-if v-else dbclick 操作 isEdit
// 自动聚焦
// 1. $nextTick $refs 获取到dom进行focus获取焦点
// 2. 封装v-focus指令// (2) 失去焦点隐藏输入框
// blur 操作 isEdit 即可// (3) 回显标签信息
// 回显的标签信息是父组件传递过来的
// v-model实现功能 (简化代码) v-model :value 和 input
// 组件内部通过props接收, :value设置给输入框// (4) 内容修改了回车 修改标签信息
// keyup.enter, 触发事件 $emit(input, e.target.value)// ---------------------------------------------------------------------// my-table 表格组件的封装
// 1. 数据不能写死动态传递表格渲染的数据 props
// 2. 结构不能写死 - 多处结构自定义 【具名插槽】
// (1) 表头支持自定义
// (2) 主体支持自定义import MyTag from ./components/MyTag.vue
import MyTable from ./components/MyTable.vue
export default {name: TableCase,components: {MyTag,MyTable},data () {return {// 测试组件功能的临时数据tempText: 水杯,tempText2: 钢笔,goods: [{ id: 101, picture: ./assets/img/news.png, name: 梨皮朱泥三绝清代小品壶经典款紫砂壶, tag: 茶具 },{ id: 102, picture: ./assets/img/news.png, name: 全防水HABU旋钮牛皮户外徒步鞋山宁泰抗菌, tag: 男鞋 },{ id: 103, picture: ./assets/img/news.png, name: 毛茸茸小熊出没儿童羊羔绒背心73-90cm, tag: 儿童服饰 },{ id: 104, picture: ./assets/img/news.png, name: 基础百搭儿童套头针织毛衣1-9岁, tag: 儿童服饰 },]}}
}
/scriptstyle langless scoped
.table-case {width: 1000px;margin: 50px auto;img {width: 100px;height: 100px;object-fit: contain;vertical-align: middle;}
}/style子组件MyTable.vue
templatetable classmy-tabletheadtrslot namehead/slot/tr/theadtbodytr v-for(item, index) in data :keyitem.idslot namebody :itemitem :indexindex /slot/tr/tbody/table
/templatescript
export default {props: {data: {type: Array,required: true}}
};
/scriptstyle langless scoped
.my-table {width: 100%;border-spacing: 0;img {width: 100px;height: 100px;object-fit: contain;vertical-align: middle;}th {background: #f5f5f5;border-bottom: 2px solid #069;}td {border-bottom: 1px dashed #ccc;}td,th {text-align: center;padding: 10px;transition: all .5s;.red {color: red;}}.none {height: 100px;line-height: 100px;color: #999;}
}
/style子组件MyTag.vue
templatediv classmy-taginputv-ifisEditv-focusrefinpclassinputtypetextplaceholder输入标签:valuevalueblurisEdit falsekeyup.enterhandleEnter/div v-elsedblclickhandleClickclasstext{{ value }}/div/div
/templatescript
export default {props: {value: String},data () {return {isEdit: false}},methods: {handleClick () {// 双击后切换到显示状态 (Vue是异步dom更新)this.isEdit true// // 等dom更新完了再获取焦点// this.$nextTick(() {// // 立刻获取焦点// this.$refs.inp.focus()// })},handleEnter (e) {// 非空处理if (e.target.value.trim() ) return alert(标签内容不能为空)// 子传父将回车时[输入框的内容] 提交给父组件更新// 由于父组件是v-model触发事件需要触发 input 事件this.$emit(input, e.target.value)// 提交完成关闭输入状态this.isEdit false}}
}
/scriptstyle langless scoped
.my-tag {cursor: pointer;.input {appearance: none;outline: none;border: 1px solid #ccc;width: 100px;height: 40px;box-sizing: border-box;padding: 10px;color: #666;::placeholder {color: #666;}}
}
/style入口main.js注册自定义指令
import Vue from vue
import App from ./App.vueVue.config.productionTip false// 封装全局指令 focus
Vue.directive(focus, {// 指令所在的dom元素被插入到页面中时触发inserted (el) {el.focus()}
})new Vue({render: h h(App),
}).$mount(#app)