IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> JavaScript知识库 -> Vue-ref 引用-案例 -> 正文阅读

[JavaScript知识库]Vue-ref 引用-案例

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.$refs.myh1)
			// this.$refs.myh1.style.color='red'
			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
				}
			]
			//把购车勾选的水果,总价计算出来
			// let amt = 0 //总价
			// arr.filter(item => item.state).forEach(item => {
			// 	amt += item.price * item.count
			// })
			// console.log(amt)
			
			// const result=arr.filter(item=>item.state).reduce((amt,item)=>{
			// 	return amt+=item.price*item.count
			// },0)
			// console.log(result)
			
			
			const result=arr.filter(item=>item.state).reduce((amt,item)=> 
			amt+=item.price*item.count,0)
			console.log(result)
		</script>
  1. 案例效果
    在这里插入图片描述

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>
	//导入axios请求库
	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:{
			//动态计算出全选状态是true还是false
			fullState(){
				// console.log(this.list.every(item=>item.goods_state))
				return this.list.every(item=>item.goods_state)
			},
			
			//已勾选的商品总价格
			amt(){
				//先过滤,在用reduce累加
				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
		//子组件商品的勾选状态,子传父修改商品勾选的状态
		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:{
		
		//接受商品的值,使用eventbus方案,把数量传到App组件,更新哪个商品的数量
		id:{
			type:Number,
			required:true
		},
		
		//接受的num的数量值
		num:{
			type:Number,
			default:1
		}
	},
	methods:{
		//点击按钮,数值+1
		add(){
			//发送App的格式为{id,value}
			const obj={id:this.id,value:this.num+1}
			//通过eventBus将obj对象发送给App.vue
			console.log(obj)
			
			bus.$emit('share',obj)
		},
		sub(){
			if(this.num-1===0)
				return
			
			//发送App的格式为{id,value}
			const obj={id:this.id,value:this.num-1}
			//通过eventBus将obj对象发送给App.vue
			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()


  JavaScript知识库 最新文章
ES6的相关知识点
react 函数式组件 & react其他一些总结
Vue基础超详细
前端JS也可以连点成线(Vue中运用 AntVG6)
Vue事件处理的基本使用
Vue后台项目的记录 (一)
前后端分离vue跨域,devServer配置proxy代理
TypeScript
初识vuex
vue项目安装包指令收集
上一篇文章      下一篇文章      查看所有文章
加:2021-09-02 11:15:56  更:2021-09-02 11:18:47 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 15:21:59-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码