书写步骤和顺序.
- 创建一个新的脚手架
- 下载axios 和相关需求包
- 在全局main.js导入需求包和指定需求
- 通过axios请求获取到所需要的相关数据
- 申明一个空数组接收相关数据
- 循环渲染需求的页面.
- 根据具体情况书写具体代码
main.js
import Vue from 'vue'
import App from './App.vue'
import "bootstrap/dist/css/bootstrap.css"
import axios from 'axios'
axios.defaults.baseURL = "https://www.escook.cn"
Vue.prototype.$axios = axios
Vue.config.productionTip = false
new Vue({
render: h => h(App),
}).$mount('#app')
App.vue
<template>
<div>
<!-- 1.根据你想要得设置标题和标题得颜色.在对应的组件里添加对应的名字 -->
<my-header background="black" title="优衣库"
></my-header>
<div class="main">
<!-- 2.渲染页面.主体部分.循环 循环的值通过axios发起请求获取 -->
<my-goods v-for="obj in list" :key="obj.id"
:obj='obj'
></my-goods>
</div>
<my-footer
:obj='list'
@quanxuan='quanxuan'
></my-footer>
</div>
</template>
<script>
import MyFooter from './components/MyFooter.vue'
import MyGoods from './components/MyGoods.vue'
import MyHeader from './components/MyHeader.vue'
export default {
data(){
return{
list:[]
}
},
components: { MyHeader, MyGoods, MyFooter },
//2.1在初始化生命周期的时候发起请求.通过设定的this.$axios
//用await 和 async 修饰...
async created(){
const {data} = await this.$axios({
method:'get',
url:'/api/cart',
})
console.log(data.list);
//2.2把获取到对应的值赋值给事先申明好的空白数组中.
this.list = data.list
},
methods:{
quanxuan(val){
this.list.forEach(obj =>obj.goods_state = val)
}
}
}
</script>
<style lang="less" scoped>
.main{
margin: 45px 0;
}
</style>
header.vue
<template>
<div class="my-header" :style="{background}">{{title}}</div>
</template>
<script>
export default {
//1.1导入父级相应的属性在标题中添加到指定位置.
props:{
background:String,
color:{
type:String,
default:'#fff'
},
title:{
type:String,
required:true
}
}
}
</script>
<style lang="less" scoped>
.my-header {
height: 45px;
line-height: 45px;
text-align: center;
background-color: #1d7bff;
color: #fff;
position: fixed;
top: 0;
left: 0;
width: 100%;
z-index: 2;
}
</style>
goods.vue
<template>
<div class="my-goods-item">
<div class="left">
<div class="custom-control custom-checkbox">
<!-- 2.4将对应的数据渲染.包括ID -->
<input type="checkbox" class="custom-control-input" :id="obj.id" v-model="obj.goods_state"
>
<label class="custom-control-label" :for="obj.id">
<img :src="obj.goods_img" alt="">
</label>
</div>
</div>
<div class="right">
<div class="top">{{obj.goods_name}}</div>
<div class="bottom">
<span class="price">¥ {{obj.goods_price}}</span>
<span>
<!-- 2.5添加对应指定的组件. -->
<my-count
:obj='obj'
></my-count>
</span>
</div>
</div>
</div>
</template>
<script>
import MyCount from './MyCount.vue'
export default {
components: { MyCount },
//2.3从父亲那里拿数据.
props:{
obj:Object
}
}
</script>
<style lang="less" scoped>
.my-goods-item {
display: flex;
padding: 10px;
border-bottom: 1px solid #ccc;
.left {
img {
width: 120px;
height: 120px;
margin-right: 8px;
border-radius: 10px;
}
.custom-control-label::before,
.custom-control-label::after {
top: 50px;
}
}
.right {
flex: 1;
display: flex;
flex-direction: column;
justify-content: space-between;
.top{
font-size: 14px;
font-weight: 700;
}
.bottom {
display: flex;
justify-content: space-between;
padding: 5px 0;
align-items: center;
.price {
color: red;
font-weight: bold;
}
}
}
}
</style>
footer.vue
<template>
<!-- 底部 -->
<div class="my-footer">
<!-- 全选 -->
<div class="custom-control custom-checkbox">
<!-- 3.1判断全选. -->
<input type="checkbox" class="custom-control-input" id="footerCheck" v-model="isAll">
<label class="custom-control-label" for="footerCheck">全选</label>
</div>
<!-- 合计 -->
<div>
<span>合计:</span>
<!-- 3.1计算总价格 -->
<span class="price">¥ {{heji}}</span>
</div>
<!-- 按钮 -->
<!-- 3.2计算总数 -->
<button type="button" class="footer-btn btn btn-primary">结算 {{ jiesuan }}</button>
</div>
</template>
<script>
export default {
//3.拿到父级里的对应属性
props:{
obj:Array
},
computed:{
//判断全选.当isAll选择和复选框做出对应的效果
isAll:{
set(val){
this.$emit('quanxuan',val)
},
get(){
return this.obj.every(obj =>obj.goods_state === true)
},
},
jiesuan(){
return this.obj.reduce((sum,arr)=>{
if(arr.goods_state === true){
sum += arr.goods_count
}
return sum;
},0)
},
heji(){
return this.obj.reduce((sum,arr)=>{
if(arr.goods_state === true){
sum += arr.goods_count * arr.goods_price
}
return sum;
},0)
}
},
}
</script>
<style lang="less" scoped>
.my-footer {
position: fixed;
z-index: 2;
bottom: 0;
width: 100%;
height: 50px;
border-top: 1px solid #ccc;
display: flex;
justify-content: space-between;
align-items: center;
padding: 0 10px;
background: #fff;
.price {
color: red;
font-weight: bold;
font-size: 15px;
}
.footer-btn {
min-width: 80px;
height: 30px;
line-height: 30px;
border-radius: 25px;
padding: 0;
}
}
</style>
count.vue
<template>
<div class="my-counter">
<!-- 2.7渲染到当前结构里. -->
<!-- 2.8数字小于1时禁用 -->
<button type="button" class="btn btn-light" @click="obj.goods_count--">-</button>
<input type="number" class="form-control inp" v-model="obj.goods_count">
<button type="button" class="btn btn-light" @click="obj.goods_count++">+</button>
</div>
</template>
<script>
export default {
//2.6从对应的父亲获取到数据
props:{
obj:Object
},
//2.9确保数字在更新以后不可以小于等于1.如果小于等于1则默认为1
updated(){
if (this.obj.goods_count <=1){
this.obj.goods_count = 1
}
}
}
</script>
<style lang="less" scoped>
.my-counter {
display: flex;
.inp {
width: 45px;
text-align: center;
margin: 0 10px;
}
.btn, .inp{
transform: scale(0.9);
}
}
</style>
|