昨日回顾
- 生命周期- 四个阶段-八个钩子函数
初始化阶段-beforeCreate - created- 实例化前后触发
created可以获取数据-因为data和methods已经初始化
挂载阶段- beforeMount - mounted - dom挂载前后触发
mounted可以获取dom对象
数据更新阶段 beforeUpdate - updated - 数据更新前后触发
一般很少用,因为它是监听所有的数据变化-一般用watch代替
watch可以监听某个数据
组件销毁阶段 beforeDestroy -destroyed
beforeDestroy- 确定要销毁了, 但是没有销毁
http的请求工具-axios
- 市场占有率很高-用法很好
- 支持Promise,还支持在nodejs使用
通用写法
axios({
method:'get/post/delete/put/patch', // 请求类型
url: '', // 请求地址
data: {}, // 请求体参数 body参数。get只有地址参数 get没有请求体参数
params: {}, // 地址参数 最终参数会拼接到url地址上
}).then(result => {}).catch()
别名写法
axios.get(url)
axios.post(url, data) // data是请求体参数
axios.put(url, data)
axios.delete(url)
axios.patch(url, data)
- 组件的ref属性和$nextTick
- ref 可以获取真实的dom元素-可以获取组件的实例对象 ```vue
- 组件标签一个ref属性
methods: { getRef() { this.$refs.abc 就是h1的dom this.$refs.efg 获取的是 counter-com的组件的实例对象,也是它的this }
}
2. $nextTick- Vue中的渲染是异步的
> setTimeout/setInterval/ajax/Promise.then.catch
- 先执行同步代码-等到主线程执行完毕-再去(按照到时顺序)执行任务队列中异步代码
> 数据更新之后,立刻获取dom结构,dom结构是上一次的
- this.$nextTick(() => {}) // 异步更新完成-会执行这个函数确保异步更新已经完成。
> 购物车的案例-json-server- 将一个json文件变成一个服务器-开启一个服务-提供接口
- restful接口规范的接口- 业界通用的一个规范
> 同样的地址不同的类型处理不同的业务
- 用户业务- 新增用户-删除用户-更新用户-查询用户
查询用户-查询用户的列表-查询单个用户的详情<br />get- /user 查询用户的列表 /user/:id 查询单个用户的详情<br />post- /user 请求体参数 新增用户<br />put- /user/:id 请求体参数 更新用户<br />delete- /user/:id 删除用户
- 获取购物车数据
> axios.defaults.baseURL = "" // 配置基础地址
- 在created中获取数据
```javascript
export default {
data() {
return {
list: []
}
}
created() {
this.getGoodsList()
},
methods: {
getGoodsList () {
axios.get().then(result => {
this.list = result.data
})
}
}
}
1. 购物车选中问题
- checkbox想要点击图片也选中,label的属性for=”id”, id不能写死,因为商品列表是循环出来的,应该生成动态的id和动态的for
- 购物车的数据里面有id属性-应用到id属性上就可以了
<div class="custom-control custom-checkbox"> <input type="checkbox" class="custom-control-input" :id="`input_${item.id}`" /> <label class="custom-control-label" :for="`input_${item.id}`"> <img :src="item.goods_img" alt="" /> </label> </div>
2. 绑定单选框影响的购物车数据
props数据单向数据流-修改的数据-回到父组件
在子组件中v-model绑定props数据不允许,单向数据流
将数据显示到组件上-绑定了input的 checked数据-
- 监听input的change事件
- 子传父-改变的值和id传回给父组件
- 父组件监听这个事件
- 重新生成一个新数组- 找到对应的id 改变它的状态
GoodsItem.vue
<template>
<div class="cart-goods-item">
<div class="left">
<div class="custom-control custom-checkbox">
<!--:checked="item.goods_state" 只是负责展示状态 -->
<input
type="checkbox"
class="custom-control-input"
:id="`input_${item.id}`"
:checked="item.goods_state"
@change="changeChecked"
/>
<label class="custom-control-label" :for="`input_${item.id}`">
<img :src="item.goods_img" alt="" />
</label>
</div>
</div>
<div class="right">
<div class="top">{{ item.goods_name }}</div>
<div class="bottom">
<span class="price">¥ {{ item.goods_price }}</span>
<span>{{ item.goods_count }}</span>
</div>
</div>
</div>
</template>
<script>
export default {
props: ["item"],
methods: {
changeChecked(event) {
this.$emit("updateChecked", this.item.id, event.target.checked);
},
},
};
</script>
App.vue
<template>
<div id="app">
<cart-header></cart-header>
<goods-item
v-for="item in list"
:key="item.id"
:item="item"
@updateChecked="updateChecked"
></goods-item>
<cart-footer></cart-footer>
</div>
</template>
<script>
import CartHeader from "./components/CartHeader.vue";
import CartFooter from "./components/CartFooter.vue";
import GoodsItem from "./components/GoodItem.vue";
import axios from "axios";
export default {
name: "App",
components: {
CartHeader,
CartFooter,
GoodsItem,
},
data() {
return {
list: [],
};
},
created() {
this.getGoodsList();
},
methods: {
getGoodsList() {
axios.get("/goodsList").then(({ data }) => {
this.list = data;
});
},
updateChecked(id, goods_state) {
// 修改数组
// push pop shift unshift splice sort reverse
// 重新赋值一个新数组-原数组长度一样
this.list = this.list.map((item) => {
if (item.id === id) {
// 只会找到一次
item.goods_state = goods_state;
}
return item;
});
},
},
};
</script>
3. 全选状态的设定
- 全选组件在Footer中,状态的展示依赖list中是否全部都勾选, 状态肯定是父组件传给Footer的
- 父组件定义计算属性- 算出来有没有全部选中
- 传给Footer组件- 赋值给checked属性
- 监听input的值改变事件
- 触发自定义事件-将true/false => 父组件
- 父组件监听事件
- 根据true/false => 影响所有数据
Footer.vue
<template>
<div class="cart-footer">
<div class="custom-control custom-checkbox">
<input
:checked="isAll"
@change="updateChecked"
type="checkbox"
class="custom-control-input"
id="footerCheck"
/>
<label class="custom-control-label" htmlFor="footerCheck"> 全选 </label>
</div>
<div>
<span>合计:</span>
<span class="price">¥ 100</span>
</div>
<button type="button" class="footer-btn btn btn-primary">结算 (0)</button>
</div>
</template>
<script>
export default {
props: ["isAll"],
methods: {
updateChecked(event) {
// 这里没有id 这是全选按钮 true - true false- false
this.$emit("updateAll", event.target.checked);
},
},
};
</script>
App.vue
<template>
<div id="app">
<cart-header></cart-header>
<goods-item
v-for="item in list"
:key="item.id"
:item="item"
@updateChecked="updateChecked"
></goods-item>
<cart-footer :isAll="isAll" @updateAll="updateAll"></cart-footer>
</div>
</template>
<script>
import CartHeader from "./components/CartHeader.vue";
import CartFooter from "./components/CartFooter.vue";
import GoodsItem from "./components/GoodItem.vue";
import axios from "axios";
export default {
name: "App",
components: {
CartHeader,
CartFooter,
GoodsItem,
},
data() {
return {
list: [],
};
},
created() {
this.getGoodsList();
},
computed: {
isAll() {
// 计算出 是不是所有的都勾选了
return this.list.every((item) => item.goods_state);
},
},
methods: {
getGoodsList() {
axios.get("/goodsList").then(({ data }) => {
this.list = data;
});
},
updateChecked(id, goods_state) {
// 修改数组
// push pop shift unshift splice sort reverse
// 重新赋值一个新数组-原数组长度一样
this.list = this.list.map((item) => {
if (item.id === id) {
// 只会找到一次
item.goods_state = goods_state;
}
return item;
});
},
// 要将所有的状态都跟新成传过来的状态
updateAll(goods_state) {
this.list = this.list.map((item) => {
item.goods_state = goods_state; // true => true false => false
return item;
});
},
},
};
</script>
4. 算出总数量和总价格显示在Footer上
- 总价格 = 选中的商品 单价 * 数量的总和
- 总数量 = 选中的商品的数量总和
传给子组件- 子组件显示totalPrice() { return this.list.reduce((prevValue, item) => { // item.goods_state true 加 false item.goods_state return ( prevValue + (item.goods_state ? item.goods_count : 0) * item.goods_price ); }, 0); }, totalCount() { return this.list.reduce((prevValue, item) => { // item.goods_state true 加 false item.goods_state return prevValue + (item.goods_state ? item.goods_count : 0); }, 0); },
5.动态组件
川剧变脸- 一个人可以不断的切换多张脸
- 一个位置可以切换不同类型的组件
用到了Vue的内置组件- component
<component :is="变量" />
// 变量是组件的名字-注册组件的名字
- 展示多少个组件,就要创建多少个.vue文件
```vue