1. 什么是 ref 引用
App.vue
<template>
<div class="app-container">
<h1 ref="myh1">App 根组件</h1>
<button @click="showThis">打印this</button>
<hr />
<div class="box">
<!-- 渲染 Left 组件和 Right 组件 -->
</div>
</div>
</template>
<script>
export default {
methods:{
showThis(){
console.log(this.$refs.myh1)
this.$refs.myh1.style.color='red'
}
}
}
</script>
<style lang="less">
.app-container {
padding: 1px 20px 20px;
background-color: #efefef;
}
.box {
display: flex;
}
</style>
2. 使用 ref 引用 DOM 元素
如果想要使用 ref 引用页面上的 DOM 元素,则可以按照如下的方式进行操作:
3. 使用 ref 引用组件实例
如果想要使用 ref 引用页面上的组件实例,则可以按照如下的方式进行操作:
App.vue
<template>
<div class="app-container">
<h1 ref="myh1">App 根组件</h1>
<button @click="showThis">打印this</button>
<button @click="onReset">重置Left组件</button>
<hr />
<div class="box">
<!-- 渲染 Left 组件和 Right 组件 -->
<Left ref="comLeft"></Left>
</div>
</div>
</template>
<script>
import Left from '@/components/Left.vue'
export default {
methods:{
showThis(){
console.log(this)
},
onReset(){
this.$refs.comLeft.resetCount()
}
},
components:{
Left
}
}
</script>
<style lang="less">
.app-container {
padding: 1px 20px 20px;
background-color: #efefef;
}
.box {
display: flex;
}
</style>
left.vue
<template>
<div class="left-container">
<h3>Left 组件-----{{count}}</h3>
<button @click="count+=1">+1</button>
<button @click="resetCount">重置</button>
</div>
</template>
<script>
export default {
data(){
return {
count:0
}
},
methods:{
resetCount(){
this.count=0
}
}
}
</script>
<style lang="less">
.left-container {
padding: 0 20px 20px;
background-color: orange;
min-height: 250px;
flex: 1;
}
</style>
数组some循环
<script>
const arr = ['hello', 'hello2', 'hello1']
arr.some((item, index) => {
if (item === 'hello2') {
console.log(index)
return true
}
})
</script>
数组reduce方法
<script>
const arr = [{
id: 1,
name: '西瓜',
'state': true,
price: 10,
count: 1
},
{
id: 2,
name: '香蕉',
'state': false,
price: 20,
count: 2
},
{
id: 3,
name: '香蕉',
'state': true,
price: 30,
count: 3
}
]
const result=arr.filter(item=>item.state).reduce((amt,item)=>
amt+=item.price*item.count,0)
console.log(result)
</script>
- 案例效果
2. 实现步骤
① 初始化项目基本结构 ② 封装 MyHeader 组件 ③ 基于 axios 请求商品列表数据( GET 请求,地址为 https://www.escook.cn/api/cart ) ④ 封装 MyFooter 组件 ⑤ 封装 MyGoods 组件 ⑥ 封装 MyCounter 组件
App.vue:
<template>
<div class="app-container">
<!-- <p>{{fullState}}</p> -->
<Header></Header>
<p>{{amt}}</p>
<!-- 循环展示商品信息 -->
<Goods v-for="item in list"
:key=""
:id="item.id"
:title="item.goods_name"
:pic="item.goods_img"
:price="item.goods_price"
:state="item.goods_state"
:count="item.goods_count"
@state-change="getNewState"
>
</Goods>
<Footer :isfull="fullState" :amout="amt" :all="total" @full-change="getFullState"></Footer>
</div>
</template>
<script>
import axios from 'axios'
import Header from '@/components/Header/Header.vue'
import Goods from '@/components/Goods/Goods.vue'
import Footer from '@/components/Footer/Footer.vue'
import bus from '@/components/eventBus.js'
export default {
data() {
return {
list: []
}
},
computed:{
fullState(){
return this.list.every(item=>item.goods_state)
},
amt(){
return this.list.filter(item=>item.goods_state).reduce((total,item)=>
total+=item.goods_price*item.goods_count
,0)
},
total(){
return this.list.filter(item=>item.goods_state).reduce((t,item)=>(t+=item.goods_count),0)
}
},
methods: {
async initCarList() {
const {
data: res
} = await axios.get('https://www.escook.cn/api/cart')
console.log(res)
if (res.status === 200) {
this.list = res.list
}
},
getNewState(e){
console.log('父组件接受到子组件的数据')
console.log(e)
this.list.some(item=>{
if(item.id===e.id){
item.goods_state=e.value
return true
}
})
},
getFullState(e){
this.list.forEach(item=>item.goods_state=e)
}
},
created() {
this.initCarList()
bus.$on('share',(val)=>{
console.log('app组件接受到的值为',val)
this.list.some(item=>{
if(item.id===val.id){
item.goods_count=val.value
return true
}
})
})
},
components: {
Header,
Goods,
Footer
}
}
</script>
<style lang="less" scoped>
.app-container {
padding-top: 45px;
padding-bottom: 50px;
}
</style>
Header.vue
<template>
<div class="header-container">标题</div>
</template>
<script>
export default {}
</script>
<style lang="less" scoped>
.header-container {
font-size: 12px;
height: 45px;
width: 100%;
background-color: #1d7bff;
display: flex;
justify-content: center;
align-items: center;
color: #fff;
position: fixed;
top: 0;
z-index: 999;
}
</style>
Footer.vue
<template>
<div class="footer-container">
<!-- 左侧的全选 -->
<div class="custom-control custom-checkbox">
<input type="checkbox" class="custom-control-input" id="cbFull" :checked="isfull" @change="fullChange" />
<label class="custom-control-label" for="cbFull">全选</label>
</div>
<!-- 中间的合计 -->
<div>
<span>合计:</span>
<span class="total-price">¥{{ amout.toFixed(2) }}</span>
</div>
<!-- 结算按钮 -->
<button type="button" class="btn btn-primary btn-settle">结算({{all}})</button>
</div>
</template>
<script>
export default {
props: {
isfull: {
type: Boolean,
default: true
},
amout: {
type: Number,
default: 0
},
all: {
type: Number,
default: 0
}
},
methods: {
fullChange(e) {
console.log(e.target.checked)
this.$emit('full-change', e.target.checked)
}
}
}
</script>
<style lang="less" scoped>
.footer-container {
font-size: 12px;
height: 50px;
width: 100%;
border-top: 1px solid #efefef;
position: fixed;
bottom: 0;
background-color: #fff;
display: flex;
justify-content: space-between;
align-items: center;
padding: 0 10px;
}
.custom-checkbox {
display: flex;
align-items: center;
}
#cbFull {
margin-right: 5px;
}
.btn-settle {
height: 80%;
min-width: 110px;
border-radius: 25px;
font-size: 12px;
}
.total-price {
font-weight: bold;
font-size: 14px;
color: red;
}
</style>
Goods.vue
<template>
<div class="goods-container">
<!-- 左侧图片 -->
<div class="thumb">
<div class="custom-control custom-checkbox">
<!-- 复选框 -->
<input type="checkbox" class="custom-control-input" :id="'cb'+id" :checked="state"
@change="stateChange"/>
<label class="custom-control-label" :for="'cb'+id">
<!-- 商品的缩略图 -->
<img :src="pic" alt="" />
</label>
</div>
</div>
<!-- 右侧信息区域 -->
<div class="goods-info">
<!-- 商品标题 -->
<h6 class="goods-title">{{title}}</h6>
<div class="goods-info-bottom">
<!-- 商品价格 -->
<span class="goods-price">¥{{price}}</span>
<!-- 商品的数量 -->
<Counter :num="count" :id="id"></Counter>
</div>
</div>
</div>
</template>
<script>
import Counter from '@/components/Counter/Counter.vue'
export default {
props:{
id:{
required:true,
type:Number
},
title:{
default: '',
type:String
},
pic:{
default: '',
type:String
},
price:{
default:0,
type:Number
},
state:{
default: 0,
type:Boolean
},
count:{
type:Number,
default:1
}
},
methods:{
stateChange(e){
const newState=e.target.checked
console.log(newState)
console.log(this.id)
this.$emit('state-change',{id:this.id,value:newState})
}
},
components:{
Counter
}
}
</script>
<style lang="less" scoped>
.goods-container {
+ .goods-container {
border-top: 1px solid #efefef;
}
padding: 10px;
display: flex;
.thumb {
display: flex;
align-items: center;
img {
width: 100px;
height: 100px;
margin: 0 10px;
}
}
.goods-info {
display: flex;
flex-direction: column;
justify-content: space-between;
flex: 1;
.goods-title {
font-weight: bold;
font-size: 12px;
}
.goods-info-bottom {
display: flex;
justify-content: space-between;
.goods-price {
font-weight: bold;
color: red;
font-size: 13px;
}
}
}
}
</style>
Counter.vue
<template>
<div class="number-container d-flex justify-content-center align-items-center">
<!-- 减 1 的按钮 -->
<button type="button" class="btn btn-light btn-sm" @click="sub">-</button>
<!-- 购买的数量 -->
<span class="number-box">{{num}}</span>
<!-- 加 1 的按钮 -->
<button type="button" class="btn btn-light btn-sm" @click="add">+</button>
</div>
</template>
<script>
import bus from '@/components/eventBus.js'
export default {
props:{
id:{
type:Number,
required:true
},
num:{
type:Number,
default:1
}
},
methods:{
add(){
const obj={id:this.id,value:this.num+1}
console.log(obj)
bus.$emit('share',obj)
},
sub(){
if(this.num-1===0)
return
const obj={id:this.id,value:this.num-1}
console.log(obj)
bus.$emit('share',obj)
}
}
}
</script>
<style lang="less" scoped>
.number-box {
min-width: 30px;
text-align: center;
margin: 0 5px;
font-size: 12px;
}
.btn-sm {
width: 30px;
}
</style>
eventBus.js
import Vue from 'vue'
export default new Vue()
|