2.1 Vue.js 关于插槽slot
我其实也没什么要说的,主要都在代码和相应的注释里面了,这个东西不好说,我感觉只能意会不能言传
匿名插槽 & 具名插槽
还是放到 VScode 或者 Hbuilder 里面看代码....
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <title> </title> 5 </head> 6 <body> 7 <div id="app"> 8 <slot-test> 9 <p>使用插槽分发内容</p> 10 <h1 slot="header">插槽测试!</h1> 11 <p>在组件中,没有指定插槽名称的元素将被置于默认插槽中</p> 12 <p slot="none">指定到不存在的插槽中的内容将不会被显示</p> 13 </slot-test> 14 </div> 15 <script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.min.js"></script> 16 <script type="text/javascript"> 17 let SlotTest = { 18 template: '<div>' + 19 '<slot name="header">相当于占位元素,因此这些文字也不会被渲染</slot>' + // 具名插槽 20 '<slot></slot>' + // 默认插槽 21 '</div>' 22 } 23 let vm = new Vue({ // Vue实例 24 el: '#app', 25 components: { SlotTest } 26 }) 27 </script> 28 </body> 29 </html>
看完并用F12魔法进行操作之后,你会发现,
1. 一般只要没有被注明 slot = " xxx " 属性的标签 就会被自动纳入到匿名插槽里面
2. 具名插槽就是 ” 调用 " 有 slot 名字的 标签
作用域插槽
slot-scope vue 2.5 之前叫 scope ,我先说说我认为的作用域插槽
作用域插槽就是为了让父组件能够运用到子组件的数据
这句话其实也是道不清说不白,我还是建议有缘人拿我的代码来实地操作一下
主要就是一个这个结构,可能有些点说法张冠李戴,但是大致该怎么用是了解的了,希望有缘人指正批评
1 <!DOCTYPE html> 2 <html lang="zh-CN"> 3 4 <head> 5 <meta charset="UTF-8"> 6 <title>组件</title> 7 <script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script> 8 </head> 9 10 <body> 11 <div id="app"> 12 <!-- 这个是测试组件调用的情况 --> 13 <component :is="view"> 14 </component> 15 <span style="color: grey;font-size: smaller;"><i>/////// 分割线 //////</i></span> 16 <br> 17 <!-- 测试插槽 --> 18 <view_2 :text="text"> 19 <!-- 大的其实是作用域插槽 --> 20 <template slot-scope="{shit}"> 21 <!-- 记住了,一定是对象储存 不能是 slo-scope = "shit" 不然输出是{ "shit" : xxx } --> 22 <h2 style="color:rgb(219, 144, 144)">{{shit}}</h2> <!-- 这个是作用域插槽里面的匿名插槽(因为没有名字) --> 23 <h2 slot="namedSlot" style="color:rgb(174, 184, 228)">这是具名插槽 shit:{{shit}}</h2> <!-- 具名插槽 --> 24 </template> 25 </view_2> 26 <!-- 测试组件切换 --> 27 <button @click="toggle('view_1')">点击变成view_1</button> 28 <button @click="toggle('view_2')">点击变成view_2</button> 29 </div> 30 </body> 31 32 <script> 33 let view_1 = { 34 template: "<h1> view_1 </h1>" 35 } 36 let view_2 = { 37 props: { 38 text: { 39 type: Number, 40 default() { 41 return 42 } 43 } 44 }, 45 template: function () { // 为什么写函数呢,可能会有人会问,因为这个东西会让风格统一,而且是个立即执行函数,不然页面没输出 46 return '<div> \n ' + // 这里一个要写一个大的盒子框起来,不然这个东西只会认一个标签 47 ' <h1> this is a test for slot-scope </h1> \n' + 48 // 匿名插槽 49 ' <slot :shit="text+111"></slot>\n' + 50 // 具名插槽 51 ' <slot name="namedSlot" :shit="text"></slot>\n' + 52 ' </div>' 53 }() 54 55 // 其实你这样写也没差的 56 // template: 57 // ' <div> \n '+ // 这里一个要写一个大的盒子框起来,不然这个东西只会认一个标签 58 // ' <h1> this is a test for slot-scope </h1> \n' + 59 // ' <slot :shit="text+111"></slot>\n'+ 60 // ' <slot name="namedSlot" :shit="text"></slot>\n'+ 61 // ' </div>' 62 63 } 64 var vm = new Vue({ 65 el: '#app', 66 components: { 67 view_1, 68 view_2 69 }, 70 data() { 71 return { 72 text: 123, 73 view: view_2 74 } 75 }, 76 methods: { 77 toggle(view) { 78 this.view = view 79 } 80 } 81 }); 82 </script> 83 84 </html>
在看完之后,你会发现,shit 是一个 插槽里面定义的 一个由 上级组件 传的text 定义的 然后 shit又被回传给了上级组件
slotscope = "{shit}",确实感觉有点像套娃 捞数据的
但是 大致的简单例子就是这样,复杂的可以用来做表格,比如我从书里看到的这个,有缘人可以尝试看一下,收获良多
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <title></title> 5 </head> 6 <body> 7 <style> 8 .btn { 9 outline: none; 10 border: none; 11 cursor: pointer; 12 padding: 5px 12px; 13 } 14 .btn-text { 15 color: #409eff; 16 background-color: transparent; 17 } 18 .btn-text:hover { 19 color: #66b1ff; 20 } 21 .fly-table { 22 width: 400px; 23 text-align: left; 24 line-height: 42px; 25 border: 1px solid #eee; 26 user-select: none; 27 } 28 </style> 29 <div id="app"> 30 <h2>Fly Table Component</h2> 31 <button 32 class="btn btn-text" 33 title="点击使数组倒序" 34 @click="handleReverse"> 35 倒序 36 </button> 37 <fly-table 38 :fields="fields" 39 :goods="goods"> 40 <!-- 组件标签包裹着的内容将被分发 --> 41 <!-- 思考下,是否可以在fly-table组件中直接书写这段代码? --> 42 <template slot-scope="{ row, col }"> 43 <span 44 v-if="col.prop !== 'operate'"> 45 {{ row[col.prop] }} 46 </span> 47 <button 48 class="btn btn-text" 49 v-else 50 @click="handleMarked(row)"> 51 {{row.isMarked?"取消标记":'标记'}} 52 </button> 53 </template> 54 55 </fly-table> 56 </div> 57 <script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.min.js"></script> 58 <script type="text/javascript"> 59 let FlyTable = { 60 props: { // 组件接收从父组件传入的数据 61 fields: { 62 type: Array, 63 default () { 64 return [] 65 } 66 }, 67 goods: { 68 type: Array, 69 default () { 70 return [] 71 } 72 } 73 }, 74 template: function () { 75 return '<table class="fly-table">\n' + 76 ' <tr>\n' + 77 ' <th\n' + 78 ' v-for="(col, cIndex) in fields"\n' + 79 ' :key="cIndex">\n' + 80 ' {{ col.label }}\n' + 81 ' </th>\n' + 82 ' </tr>\n' + 83 ' <tr\n' + 84 ' v-for="(row, rIndex) in goods"\n' + 85 ' :key="rIndex"\n' + 86 ' :style="{color: row.isMarked ? \'#ea4335\' : \'\'}">\n' + 87 ' <td\n' + 88 ' style="border-top: 1px solid #eee"\n' + 89 ' v-for="(col, cIndex) in fields"\n' + 90 ' :key="cIndex">\n' + 91 // slot应写在子组件中,用于接收父组件分发的内容 92 ' <slot :row="row" :col="col"></slot>\n' + 93 ' </td>\n' + 94 ' </tr>\n' + 95 ' </table>' 96 }() // 其实这个template 就是一个字符串 但是作者写了函数来看 风格统一 但是必须是立即执行函数 不然没有这个字符串 97 } 98 // 声明 Vue 实例 99 let vm = new Vue({ 100 el: '#app', 101 components: { FlyTable }, 102 data () { 103 return { 104 fields: [ 105 { 106 label: '名称', 107 prop: 'name' 108 }, 109 { 110 label: '数量', 111 prop: 'quantity' 112 }, 113 { 114 label: '价格', 115 prop: 'price' 116 }, 117 { 118 label: '', 119 prop: 'operate' 120 } 121 ], 122 goods: [ 123 { 124 name: '苹果', 125 quantity: 200, 126 price: 6.8, 127 isMarked: false 128 }, 129 { 130 name: '西瓜', 131 quantity: 50, 132 price: 4.8, 133 isMarked: false 134 }, 135 { 136 name: '榴莲', 137 quantity: 0, 138 price: 22.8, 139 isMarked: false 140 } 141 ] 142 } 143 }, 144 methods: { 145 handleReverse () { 146 this.goods.reverse() 147 }, 148 handleMarked (row) { 149 row.isMarked = !row.isMarked 150 } 151 } 152 }) 153 </script> 154 </body> 155 </html>
总结
前几天只是看到了有slot这个东西,也不是很理解,今天看弄懂了一点,然后自己试着敲了一下代码才知道有些地方不对
好了 该吃饭了
请有缘人发现错误 给我说一哈
Let it roll