Vue中的组件插槽

1.组件插槽

<body>
    <div id="app">
        <test-jerry>有bug发生</test-jerry>
        <test-jerry></test-jerry>
    </div>
    <script>
        /*
            组件插槽
            在子组件中需要提供一个位置,组件标签中得内容会传递给solt中
        */
        Vue.component("test-jerry",{
            data(){
                return {
                    num:0,
                }
            },
            template:`
                <div> 
                    <strong>ERROR:</strong>
                    <slot>123</slot>
                </div>
              `
        })
        
        var vm = new Vue({
            el:"#app" ,
            data:{

            }
        })
    </script>
</body>

2.具名插槽

<body>
    <div id="app">
        <base-layout>
            <p slot="header">标题信息</p>
            <p>主要内容1</p>
            <p>主要内容2</p>
            <p slot="footer">底部信息</p>
        </base-layout>

        <base-layout>
            <template slot="header">
                <p>标题信息1</p>
                <p>标题信息2</p>
            </template>
            <p>主要内容1</p>
            <p>主要内容2</p>
        <template slot="footer">
            <p>底部信息1</p>
            <p>底部信息2</p>
        </template>
    </base-layout>
    </div>
    <script>
        /*
            具名插槽得用法
        */
       Vue.component("base-layout",{
           data(){
               return {

               }
           },
           template:`
                <div>
                    <header>
                        <slot name='header'></slot>
                    </header>    
                    <main>
                        <slot></slot>
                    </main>    
                    <footer>
                        <slot name='footer'></slot>
                    </footer>    
                </div>
           `
       })

       var vm  = new Vue({
           el:"#app" ,
           data:{

           }
       })
    </script>
</body>

3.作用域插槽

<body>
    <div id="app">
        <fruit-list :list='list' >
            <template slot-scope="sloatprops">
                <strong  class="current" v-if='sloatprops.info.id==1'>{{sloatprops.info.name}}</strong>
                <span v-else>{{sloatprops.info.name}}</span>
            </template>
        </fruit-list>
    </div>
    <script>
        /*
            作用域插槽
            应用场景:父组件对子组件得内容进行加工处理
            1.插槽定义
            从父组件中能够得到子组件得数据   
        */
       Vue.component('fruit-list',{
           props:['list'],
            template:   `
                <div> 
                    <li :key="item.id" v-for="item  in list"> 
                        <slot :info='item'>     
                        {{item.name}}
                        </slot>
                    </li>
                </div>
            `   
       })
        var vm = new Vue({
            el:"#app" ,
            data:{
                list:[{
                    id:1,
                    name:'apple'
                },{
                    id:2,
                    name:'orange'
                },{
                    id:3,
                    name:'banana'
                }]
            },
            methods: {
                
            },
        })


    </script>
</body>

4.购物车案例

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Document</title>
  <style type="text/css">
    .container .cart {
      width: 300px;
      margin: auto;
    }
    .container .title {
      background-color: lightblue;
      height: 40px;
      line-height: 40px;
      text-align: center;
      /*color: #fff;*/  
    }
    .container .total {
      background-color: #FFCE46;
      height: 50px;
      line-height: 50px;
      text-align: right;
    }
    .container .total button {
      margin: 0 10px;
      background-color: #DC4C40;
      height: 35px;
      width: 80px;
      border: 0;
    }
    .container .total span {
      color: red;
      font-weight: bold;
    }
    .container .item {
      height: 55px;
      line-height: 55px;
      position: relative;
      border-top: 1px solid #ADD8E6;
    }
    .container .item img {
      width: 45px;
      height: 45px;
      margin: 5px;
      cursor: pointer;
    }
    .container .item .name {
      position: absolute;
      width: 90px;
      top: 0;left: 55px;
      font-size: 16px;
    }

    .container .item .change {
      width: 100px;
      position: absolute;
      top: 0;
      right: 50px;
    }
    .container .item .change a {
      font-size: 20px;
      width: 30px;
      text-decoration:none;
      background-color: lightgray;
      vertical-align: middle;
    }
    .container .item .change .num {
      width: 40px;
      height: 25px;
    }
    .container .item .del {
      position: absolute;
      top: 0;
      right: 0px;
      width: 40px;
      text-align: center;
      font-size: 40px;
      cursor: pointer;
      color: red;
    }
    .container .item .del:hover {
      background-color: orange;
    }
  </style>
</head>
<body>
  <div id="app">
    <div class="container">
      <my-cart></my-cart>
    </div>
  </div>
  <script type="text/javascript" src="js/vue.js"></script>
  <script type="text/javascript">
    
    //用模板字符串来做
    var CartTitle = {
      props:['uname'], //动态渲染数据uname
      template: `
        <div class="title">{{uname}}的商品</div>
      `
    }
    var CartList = {
      props:['list'],
      template: `
        <div>
          <div :key='item.id' v-for='item in list' class="item">
            <img :src="item.img"/>
            <div class="name">{{item.name}}</div>
            <div class="change">
              <a href="" @click.prevent @click='mov(item.id)'>-</a>
              <input type="text" class="num"  :value='item.num' @blur='changenum(item.id,$event)'/>
              <a href="" @click.prevent @click='add(item.id)'>+</a>
            </div>
            <div class="del" @click="del(item.id)">×</div>
          </div>
      `,
      methods:{
        del(id){
          /* console.log(id); */
          //把id传给父组件
          this.$emit('cart-del', id); 
        },
        changenum(id,event){
          this.$emit('change-num',{
            id: id,
            num: event.target.value,
          });
        },
        add(id){
          this.$emit('change-add', {
            pr:'+',
            id: id
          });
        },
        mov(id){
          this.$emit('change-add', {
            pr:'-',
            id: id
          });
        }
      }
    }
    var CartTotal = {
      props:['list'],
      template: `
        <div class="total">
          <span>总价:{{total}}</span>
          <button style="cursor: pointer">结算</button>
        </div>
      `,
      //这里是计算属性
      computed:{
        total(){
          //计算商品的总价钱
          var t = 0;
          this.list.forEach(item => {
            t += item.price*item.num;
          });
          return t;
        }
      }
    }
    Vue.component('my-cart',{
      //模板信息 模板字符串 里面包含三个子组件 
      //子组件定义称局部组件 模板组件
      //组件化得重构 展示购物车 
      data(){
        return {
          uname:'张三',
          list: [{
            id: 1,
            name: 'TCL彩电',
            price: 1000,
            num: 1,
            img: 'img/a.jpg'
          },{
            id: 2,
            name: '机顶盒',
            price: 1000,
            num: 1,
            img: 'img/b.jpg'
          },{
            id: 3,
            name: '海尔冰箱',
            price: 1000,
            num: 1,
            img: 'img/c.jpg'
          },{
            id: 4,
            name: '小米手机',
            price: 1000,
            num: 1,
            img: 'img/d.jpg'
          },{
            id: 5,
            name: 'PPTV电视',
            price: 1000,
            num: 1,
            img: 'img/e.jpg'
          }]
        }
      },
      template: `
        <div class='cart'>
          <cart-title :uname='uname'></cart-title>
          <cart-list :list='list' @cart-del='delcart($event)' @change-num='change($event)' @change-add='changeadd($event)'></cart-list>
          <cart-total :list='list'></cart-total>
        </div>
      `,
      components: {  //三个子组件
        'cart-title': CartTitle,
        'cart-list': CartList,
        'cart-total': CartTotal
      },
      methods: {
        delcart(id){
          //拿到id删除list中对应的数据
          //1.找到索引id
          //用到数组的API
          var index = this.list.findIndex(item =>{
              return  item.id == id;
          });
          //2.根据索引删除对应数据
          this.list.splice(index,1);
        },
        change(val){
          //根据子组件传递过来的数据更新List中的数据
          this.list.some(item =>{
            if (item.id == val.id){
              item.num = val.num;
              //终止遍历
              return true;
            }
          })
        },
        changeadd(val){
          this.list.some(item =>{
            if (item.id == val.id){
              if (val.pr == '+'){
                item.num ++;
              }else {
                if (item.num <=0) {
                  alert("你不能少于0!")
                }else {
                  item.num --;
                }
              }
              //终止遍历
              return true;
            }
          })
        },
      }
    });
    var vm = new Vue({
      el: '#app',
      data: {

      }
    });

  </script>
</body>
</html>


 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

李遇·

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值