站長資訊網
        最全最豐富的資訊網站

        vue插槽解決什么問題

        vue插槽解決的問題:引入的子組件標簽中間不允許寫內容的。插槽(Slot)是vue為組件的封裝者提供的能力;允許開發者在封裝組件時,把不確定的、希望由用戶指定的部分定義為插槽;可以把插槽認為是組件封裝期間,為用戶預留的內容的占位符。

        vue插槽解決什么問題

        本教程操作環境:windows7系統、vue3版,DELL G3電腦。

        什么是插槽?

        我們知道,在vue中,引入的子組件標簽中間是不允許寫內容的。為了解決這個問題,官方引入了插槽(slot)的概念。

        插槽,其實就相當于占位符。它在組件中給你的HTML模板占了一個位置,讓你來傳入一些東西。插槽又分為匿名插槽具名插槽以及作用域插槽

        你可能不太明白,為什么我要給子組件中傳入HTML,而不直接寫在子組件中呢?答案是這樣的。你可以想象一個場景,你有五個頁面,這五個頁面中只有一個區域的內容不一樣,你會怎么去寫這五個頁面呢?復制粘貼是一種辦法,但在vue中,插槽(slot)是更好的做法。

        vue插槽解決什么問題

        匿名插槽


        匿名插槽,我們又可以叫它單個插槽或者默認插槽。與具名插槽相對,它不需要設置name屬性。(它隱藏的name屬性為default。)

        例子:

        文件目錄如下,Home組件是HelloWorld的父組件。

        vue插槽解決什么問題

        • 在HelloWorld中寫一個匿名插槽

        <template>   <div class="hello">      Helloworld組件       <div class = 'slotTxt'>        <slot></slot>      </div>    </div> </template>  <script> export default {  } </script>  <!-- Add "scoped" attribute to limit CSS to this component only --> <style scoped lang="less"> .hello{   width:100%;   height:300px;   background:#ccc;   margin-top:50px;   .slotTxt{     width:500px;     height:200px;     margin:30px auto;     background:red;   } } </style>
        登錄后復制

        • 在Home組件中引入子組件,并在子組件標簽中寫入內容

        <template>   <div class="home">     我是Home父組件     <HelloWorld>       <!-- 沒有插槽,這里的內容不顯示 -->       <h1>我是helloworld中的插槽啊</h1>       </HelloWorld>   </div> </template>  <script> import HelloWorld from '@/components/HelloWorld.vue' export default {   name: 'home',   components: {     HelloWorld   } } </script>
        登錄后復制

        效果

        vue插槽解決什么問題

        不難看出,HelloWorld標簽中的內容(紅色部分)已經顯示出來了。

        具名插槽


        上面已經說過,插槽有一個name屬性。與匿名插槽相對,加了name屬性的匿名插槽就是具名插槽。

        • HelloWorld組件中寫入name屬性分別為left和right的插槽

        <template>   <div class="hello">      Helloworld組件       <div class = 'slotLeft'>        <slot name='left'></slot>      </div>       <div class = 'slotRight'>        <slot name='right'></slot>      </div>    </div> </template>  <script> export default {  } </script>  <!-- Add "scoped" attribute to limit CSS to this component only --> <style scoped lang="less"> .hello{   width:700px;   height:300px;   background:#ccc;   margin: 0 auto;   margin-top:50px;   .slotLeft{     width:300px;     height:200px;     float:left;     background:red;   }   .slotRight{     width:300px;     height:200px;     float:right;     background:pink;   } } </style>
        登錄后復制

        • Home組件通過在template上寫v-slot:name來使用具名插槽

        <template>   <div class="home">     我是Home父組件     <HelloWorld>       <template v-slot:left>          <h1>name屬性為left</h1>        </template>       <template v-slot:right>          <h1>name屬性為right</h1>        </template>           </HelloWorld>   </div> </template>  <script> import HelloWorld from '@/components/HelloWorld.vue' export default {   name: 'home',   components: {     HelloWorld   } } </script> <style lang="less" scoped> .home{   width:900px;   margin:0 auto;   background:yellow;   padding-bottom:100px; } </style>
        登錄后復制

        注意 v-slot 只能添加在template標簽上 (只有一種例外情況)。

        • 效果

        vue插槽解決什么問題

        • 例外情況(被廢棄的slot=‘name’)
          帶slot屬性的具名插槽自 2.6.0 起被廢棄,vue3.x被完全廢棄。只有vue3之前的cli可以使用。

        <template>   <div class="home">     我是Home父組件     <HelloWorld>       <h1 slot='left'>name屬性為left</h1>         <h1 slot='right'>name屬性為right</h1>       </HelloWorld>   </div> </template>  <script> import HelloWorld from '@/components/HelloWorld.vue' export default {   name: 'home',   components: {     HelloWorld   } } </script> <style lang="less" scoped> .home{   width:900px;   margin:0 auto;   background:yellow;   padding-bottom:100px; } </style>
        登錄后復制

        效果同上。

        • 具名插槽的小知識點
          跟 v-on 和 v-bind 一樣,v-slot 也有縮寫,即把參數之前的所有內容 (v-slot:) 替換為字符 #。例如 v-slot:header 可以被重寫為 #header。

        作用域插槽


        作用域插槽其實就是可以傳遞數據的插槽。子組件中的一些數據想在父組件中使用,必須通過規定的方法來傳遞。在官方文檔中提出了一條規則,**父級模板里的所有內容都是在父級作用域中編譯的。子模板里的所有內容都是在子作用域中編譯的。**如果你在父組件直接使用子組件中的值,是會報錯的。

        匿名插槽的作用域插槽

        為了讓 子組件中的數據 在父級的插槽內容中可用,我們可以將 數據 作為 元素的一個特性綁定上去:

        語法:v-bind:users="user"
        登錄后復制

        • 子組件HelloWorld代碼

        <template>   <div class="hello">      Helloworld組件        <div class='slotLeft'>        <slot v-bind:users="user"></slot>      </div>          </div> </template>  <script> export default {   data(){     return{       user:{         name:'oralinge',         age:18       }     }     } } </script>  <!-- Add "scoped" attribute to limit CSS to this component only --> <style scoped lang="less"> .hello{   width:700px;   height:300px;   background:#ccc;   margin: 0 auto;   margin-top:50px;   .slotLeft{     width:300px;     height:200px;     // float:left;     background:red;     margin:20px auto   }   .slotRight{     width:300px;     height:200px;     float:right;     background:pink;   } } </style>
        登錄后復制

        綁定在 元素上的特性(v-bind:users=“user”)被稱為插槽 prop?,F在在父級作用域中,我們可以使用帶值的 v-slot 來定義我們提供的插槽 prop 的名字。

        語法:v-slot:default="隨意取的名字"  // default可省略,簡寫為v-slot="隨意取的名字"
        登錄后復制

        • 父組件Home代碼

        <template>   <div class="home">     我是Home父組件     <HelloWorld>       <template  v-slot:default="slotProps">          <h1>{{slotProps.users.name}}</h1>        </template>     </HelloWorld>   </div> </template>  <script> import HelloWorld from '@/components/HelloWorld.vue' export default {   name: 'home',   components: {     HelloWorld   } } </script> <style lang="less" scoped> .home{   width:900px;   margin:0 auto;   background:yellow;   padding-bottom:100px; } </style>
        登錄后復制

        注意:
        父組件中的slotProps可以是隨意取的。
        子組件中users是隨意取的,與之對應的是父組件中的users。
        子組件中的user為數據。

        效果

        vue插槽解決什么問題

        具名插槽的作用域插槽

        與匿名插槽同理,只需要把default替換成插槽的name值即可。

        • 子組件HelloWorld代碼

        <template>   <div class="hello">      Helloworld組件        <div class='slotLeft'>        <slot name='helloWorld' v-bind:users="user"></slot>      </div>          </div> </template>  <script> export default {   data(){     return{       user:{         name:'hello world',         age:18       }     }     } } </script>  <!-- Add "scoped" attribute to limit CSS to this component only --> <style scoped lang="less"> .hello{   width:700px;   height:300px;   background:#ccc;   margin: 0 auto;   margin-top:50px;   .slotLeft{     width:300px;     height:200px;     // float:left;     background:red;     margin:20px auto   }   .slotRight{     width:300px;     height:200px;     float:right;     background:pink;   } } </style>
        登錄后復制

        • 父組件Home代碼

        <template>   <div class="home">     我是Home父組件     <HelloWorld>       <template  v-slot:helloWorld="slotProps">          <h1>{{slotProps.users.name}}</h1>        </template>     </HelloWorld>   </div> </template>  <script> import HelloWorld from '@/components/HelloWorld.vue' export default {   name: 'home',   components: {     HelloWorld   } } </script> <style lang="less" scoped> .home{   width:900px;   margin:0 auto;   background:yellow;   padding-bottom:100px; } </style>
        登錄后復制

        效果

        vue插槽解決什么問題

        注意:
        默認插槽的縮寫語法不能和具名插槽混用,因為它會導致作用域不明確。

        vue插槽解決什么問題

        另,slot-scope寫法在2.6之后已廢棄,作用與上面相同,在此不做解釋。

        上面的寫法是不是覺得有些麻煩?別著急,我們來看一看解構插槽 Prop。

        解構插槽 Prop

        作用域插槽的內部工作原理是將你的插槽內容包括在一個傳入單個參數的函數里:

        function (slotProps) {   // 插槽內容 }
        登錄后復制

        這意味著 v-slot 的值實際上可以是任何能夠作為函數定義中的參數的 JavaScript 表達式。所以在支持的環境下 (單文件組件或現代瀏覽器),你也可以使用 ES2015 解構來傳入具體的插槽 prop。

        語法:v-slot="{ users }"
        登錄后復制

        • HelloWold組件

        <template>   <div class="hello">      Helloworld組件        <div class='slotLeft'>        <slot v-bind:users="user"></slot>      </div>          </div> </template>  <script> export default {   data(){     return{       user:{         name:'hello world',         age:18       }     }     } } </script>  <!-- Add "scoped" attribute to limit CSS to this component only --> <style scoped lang="less"> .hello{   width:700px;   height:300px;   background:#ccc;   margin: 0 auto;   margin-top:50px;   .slotLeft{     width:300px;     height:200px;     // float:left;     background:red;     margin:20px auto   }   .slotRight{     width:300px;     height:200px;     float:right;     background:pink;   } } </style>
        登錄后復制

        • Home組件

        <template>   <div class="home">     我是Home父組件     <HelloWorld>       <template  v-slot="{ users }">          <h1>{{users.name}}</h1>        </template>     </HelloWorld>   </div> </template>  <script> import HelloWorld from '@/components/HelloWorld.vue' export default {   name: 'home',   components: {     HelloWorld   } } </script> <style lang="less" scoped> .home{   width:900px;   margin:0 auto;   background:yellow;   padding-bottom:100px; } </style>
        登錄后復制

        • 效果

        vue插槽解決什么問題

        • 重命名—-更改users這個名字

        <template>   <div class="home">     我是Home父組件     <HelloWorld>       <template  v-slot="{ users:person }">          <h1>{{person.name}}</h1>        </template>     </HelloWorld>   </div> </template>  <script> import HelloWorld from '@/components/HelloWorld.vue' export default {   name: 'home',   components: {     HelloWorld   } } </script> <style lang="less" scoped> .home{   width:900px;   margin:0 auto;   background:yellow;   padding-bottom:100px; } </style>
        登錄后復制

        效果如上圖。

        • 定義后備內容,用于插槽 prop 是 undefined 的情形
          此處按照官方文檔的寫法會出現語法報錯,后期應該會修復(有知道的麻煩通知一聲)。

        <template>   <div class="home">     我是Home父組件     <HelloWorld>       <template >          <h1 v-slot="{ users = { name: '1111' } }">{{users.name}}</h1>        </template>     </HelloWorld>   </div> </template>  <script> import HelloWorld from '@/components/HelloWorld.vue' export default {   name: 'home',   components: {     HelloWorld   } } </script> <style lang="less" scoped> .home{   width:900px;   margin:0 auto;   background:yellow;   padding-bottom:100px; } </style>
        登錄后復制

        使用場景


        • 復用公共組件
          代碼示例如下:

        <template>   <div>     <div class="title-box">       <span class="title">{{title}}</span>       <div class="right">         <slot name="right"></slot>       </div>     </div>     <div class="content-box">       <slot></slot>     </div>   </div> </template> <script> export default {   data () {     return {     }   },   props: {     title: {       type: String,       required: true     }   } } </script> <style lang="scss" scoped> .title-box {   padding: 16px 0;   border-bottom: 1px solid #eff1f5;   .title {     font-family: MicrosoftYaHei;     font-size: 24px;     color: #283039;     letter-spacing: 0;     line-height: 24px;     &::before {       width: 4px;       margin-right: 20px;       content: "";       background-color: #5da1ff;       display: inline-block;       height: 20px;       vertical-align: middle;     }   }   .right {     float: right;     margin-right: 20px;   } } </style>
        登錄后復制

        使用的ui框架為ivew。

        贊(0)
        分享到: 更多 (0)
        網站地圖   滬ICP備18035694號-2    滬公網安備31011702889846號
        主站蜘蛛池模板: 欧美人与动牲交a欧美精品| 亚洲av日韩av天堂影片精品| 亚洲国产精品激情在线观看| 区亚洲欧美一级久久精品亚洲精品成人网久久久久 | 久久夜色精品国产亚洲av| 无码精品久久久天天影视| 久久精品国产精品亚洲人人 | 精品人伦一区二区三区潘金莲| 色花堂国产精品第一页| 中文字幕av日韩精品一区二区| 国产亚洲精品拍拍拍拍拍| 日韩欧美一区二区三区中文精品| 无码人妻精品一区二区三区东京热| 亚洲国产精品毛片av不卡在线 | 久久精品视屏| 四虎国产精品永久地址51| 国产精品后入内射日本在线观看| 亚洲韩精品欧美一区二区三区| 精品国产午夜肉伦伦影院| 97精品伊人久久久大香线蕉| 黑人巨大精品欧美一区二区| 国产精品va久久久久久久| 精品不卡一区二区| 综合国产精品第一页| 欧美日韩精品久久久免费观看| 国产精品国产欧美综合一区| 欧美一区二区精品久久| 久久99国产精品99久久| 第一福利永久视频精品| 国产精品视频一区二区三区无码| 日韩精品人妻系列无码专区| 亚洲AV第一页国产精品| 婷婷五月深深久久精品| 亚洲精品国产美女久久久| 久久久久国产精品嫩草影院| 国产亚洲精品资在线| 国产亚州精品女人久久久久久| 国产精品无码无卡无需播放器| 国产精品福利片免费看| 国产原创精品 正在播放| 精品国产福利尤物免费|