Vue06

128 阅读4分钟

购物车案例续

补充:

限制文字的行数带...

      // 限制显示两行名字
      display: -webkit-box;
      overflow: hidden;
      -webkit-line-clamp: 2;
      -webkit-box-orient: vertical;
初始化新项目, 清空不要的东西, 下载bootstrap库, 下载less模块
vue create shopcar
yarn add bootstrap@3.4.1          下载bootstrap库
yarn add less less-loader       下载less模块
总结:

props: [] - 只能声明变量和接收, 不能类型校验

props: {} - 声明变量和校验类型规则 - 外部传入值不对则报错

获取数据

// 创建utils/request.js
// 改造 axios 添加基地址后重新导出
import axios from 'axios'
axios.defaults.baseURL = 'https://www.escook.cn'export default axios
// 创建api/cart.js
// 引入经过修改的 axios
import request from '@/utils/request'// 封装接口函数, 导出供页面使用
// 获取购物车数据 (具名导出, 跟其他可能要加入的函数进行区分)
export function getCart() {
  return request({
    // 会自动拼接上 baseURL 配置
    url: '/api/cart'
  })
}

image.png

渲染商品

<template>
  <div>
    <CartHeader bg="#1d7bff" title="我的购物车"/>
    <div class="list">
      <ProdItem
        v-for="item in list"
        :key="item.id"
        :data="item"
      />
    </div>
    <div class="footer">
      <input type="checkbox" name="" id="">
      <div class="total">合计¥1151.8</div>
      <button>结算</button>
    </div>
  </div>
</template>

image.png

单一商品选中

主要是复习了 label 标签的使用

    <input v-model="data.goods_state" class="checkbox" type="checkbox" name="" :id="data.id" />
    <label :for="data.id">
      <img
        :src="data.goods_img"
        alt=""
      />
    </label>

单一商品数量

输入框已经绑定好,

需要做修改的是加减按钮

image.png

image.png

全选

被动

  export default {
    props: ['list'],
    computed: {
      isAll() {
        return this.list.every(item=>item.goods_state)
      }
    }
  };

主动

  export default {
    props: ['list'],
    computed: {
      isAll: {
        get() {
          return this.list.every(item=>item.goods_state)
        },
        set(isChecked) {
          // 这里可以接收到全选的布尔值, 
          // 将所有商品状态改为跟全选状态一样即可
          this.list.forEach(element => {
            element.goods_state = isChecked
          });
        }
      }
    }
  };

总数量和总价格

      totalPrice() {
        // 总价=列表中所有被勾选的商品的单价乘以数量累加起来
        let res = 0
        this.list.forEach(element => {
          if (element.goods_state) {
            res += element.goods_count * element.goods_price
          }
        });
        return res
      },
      totalCount() {
        let res = 0
        this.list.forEach(element => {
          if (element.goods_state) {
            res += element.goods_count
          }
        });
        return res
      }

动态组件

动态组件是在同一个挂载点, 可以切换显示不同组件

使用动态组件:vue内置的component组件, 配合is属性

如何切换:改变is属性的值, 为要显示的组件名即可

方法:

  1. 准备被切换的 - UserName.vue / UserInfo.vue 2个组件
  1. 引入到APP.vue注册
  1. 准备变量来承载要显示的"组件名"
  1. 设置挂载点, 使用is属性来设置要显示哪个组件
  1. 点击按钮 – 修改comName变量里的"组件名"

  2. 在App.vue - 引入UserName.vue并使用显示

    总结: vue内置component组件, 配合is属性, 设置要显示的组件名字

// 目标: 动态组件 - 切换组件显示
// 场景: 同一个挂载点要切换 不同组件 显示
// 1. 创建要被切换的组件 - 标签+样式
// 2. 引入到要展示的vue文件内, 注册
// 3. 变量-承载要显示的组件名
// 4. 设置挂载点<component :is="变量"></component>
// 5. 点击按钮-切换comName的值为要显示的组件名
<template>
  <div>
    <button @click="componentName = 'UserInfo'">个人信息</button>
    <button @click="componentName = 'UserName'">账号登录</button>
    <!-- vue内置标签 component 是动态组件挂载点, 会根据绑定的 is 属性显示名字对应的组件 -->
    <component :is="componentName" />
  </div>
</template><script>
import UserInfo from '@/components/UserInfo.vue'
import UserName from '@/components/UserName.vue'
export default {
  data() {
    return { 
      componentName: 'UserInfo'
    }
  },
  components: {
    UserInfo,
    UserName
  }
}
</script><style></style>

组件缓存

优点:不会频繁的创建和销毁组件, 页面更快呈现

使用Vue内置的keep-alive组件, 可以让包裹的组件保存在内存中不被销毁

1: 可以先给UserName.vue和UserInfo.vue 注册created和destroyed生命周期事件, 观察创建和销毁过程

2: 使用keep-alive内置的vue组件, 让动态组件缓存而不是销毁

语法:

Vue内置的keep-alive组件 包起来要频繁切换的组件

初步使用

    <keep-alive>
      <component :is="componentName" />
    </keep-alive>

拓展生命周期

  • activated - 激活
  • deactivated - 失去激活状态

总结: keep-alive可以提高组件的性能, 内部包裹的标签不会被销毁和重新创建, 触发激活和非激活的生命周期方法

    activated() {
      console.log('缓存的组件被激活(显示)');
    },
    deactivated() {
      console.log('缓存的组件被隐藏');
    }

插槽使用

可以通过 slot 标签, 让组件内可以接收不同的标签结构显示

vue提供组件插槽能力, 允许开发者在封装组件时,把不确定的部分定义为插槽

给组件插入什么标签, 组件就会显示什么标签

image.png

基本操作

<template>
  <div class="topBar">
    <div class="left"></div>
    <div class="right">
      <!-- 插槽占位标签 -->
      <slot/>
    </div>
  </div>
</template><script>
export default {
​
}
</script><style lang="less" scoped>
.topBar {
  display: flex;
  justify-content: space-between;
  border: 2px solid salmon;
}
</style>
<template>
  <div>
    <!-- 员工页使用, 就要带导入员工新建员工按钮 -->
    <TopBar>
      <button>新增员工</button>
      <button>导入员工</button>
    </TopBar>
    <!-- 工资页面使用需要一个报表按钮 -->
    <TopBar>
      <button>报表</button>
    </TopBar>
  </div>
</template><script>
import TopBar from '@/components/TopBar.vue'
export default {
  components: {
    TopBar
  }
}
</script><style></style>

默认显示内容设定

目标: 如果外面不给传, 想给个默认显示内容

口诀: 夹着内容默认显示内容, 如果不给插槽slot传东西, 则使用夹着的内容在原地显示

<template>
  <div class="topBar">
    <div class="left"></div>
    <div class="right">
      <!-- 插槽占位标签 -->
      <slot>
        <!-- 如果外面没有传入, 默认显示的内容 -->
        欢迎来到我的页面
      </slot>
    </div>
  </div>
</template>

具名插槽

简化语法:v-slot: 可以被简化成#
语法:
  1. slot使用name属性区分名字
  1. template配合v-slot:名字来分发对应标签

    当组件内多处不确定的标签时:

    可以使用slot占位, 给name属性起名字来区分

    template配合v-slot:name分发要替换的标签

    <div class="left">
      <slot name="left"/>
    </div>
    <div class="right">
      <!-- 插槽占位标签 -->
      <slot name="right">
        <!-- 如果外面没有传入, 默认显示的内容 -->
        欢迎来到我的页面
      </slot>
    </div>
    <TopBar>
      <!-- v-slot: 可以被简化成# -->
      <template #left>
        一共 666 位员工
      </template>
      <template #right>
        <button>新增员工</button>
        <button>导入员工</button>
      </template>
    </TopBar>
    <!-- 工资页面使用需要一个报表按钮 -->
    <TopBar>
      <template v-slot:left>
        5月工资报表
      </template>
      <template v-slot:right>
        <button>报表</button>
      </template>
    </TopBar>

作用域插槽

子组件

      <slot :row="monthList" name="left">
        {{monthList.first}} 工资报表
      </slot>

父组件

      <template v-slot:left="scope">
       {{scope.row.second}} 工资报表
      </template>

作用域插槽具体使用场景

封装一个灵活的表格组件

自定义指令的使用方式

自定义指令文档

除了核心功能默认内置的指令 (v-modelv-show),Vue 也允许注册自定义指令。 v-xxx

html+css的复用的主要形式是组件

你需要对普通 DOM 元素进行底层操作,这时候就会用到自定义指令

image.png

<template>
  <div>
    <!-- 使用自定义指令, 跟普通vue指令一样, 请千万注意,要加上 v- 前缀 -->
    <input type="text">
    <br>
    <input type="text">
    <br>
    <input v-autofocus type="text">
  </div>
</template><script>
export default {
  // 局部指令注册
  // directives: {
    // 指令名字符串: {
        // 配置对象
        // 可以指定使用这个指令的元素, 在不同生命周期执行的函数
        // 在这些钩子函数的形参中, 默认第一个可以获取元素本身, 第二个可以用来传参
        // inserted,
        // update
    // }
  // }
  directives: {
    autofocus: {
      inserted(el) {
        console.log(el, '自动聚焦');
        el.focus()
      }
    }
  }
}
</script><style></style>