vue 进阶---ref 引用

目录

ref 引用

什么是 ref 引用

使用 ref 引用 DOM 元素

使用 ref 引用组件实例

控制文本框和按钮的按需切换

购物车案例

请求数据列表

Footer子组件

计算勾选商品价格

商品的数量

计算勾选商品总数量


ref 引用

什么是 ref 引用

ref 用来辅助开发者在 不依赖于 jQuery 的情况下 ,获取 DOM 元素或组件的引用。
每个 vue 的组件实例上,都包含一个 $refs 对象 ,里面存储着对应的 DOM 元素或组件的引用。默认情况下,
组件的 $refs 指向一个空对象
<template>
<button @click="showThis">打印 this</button>

</template>

export default {

 methods: {

 showThis() {
      // this 是当前 App 组件的实例对象
      console.log(this)

}

}

使用 ref 引用 DOM 元素

如果想要使用 ref 引用页面上的 DOM 元素 ,则可以按照如下的方式进行操作:
<h1 ref="myh1">App 根组件</h1>   //加ref属性  起名字
    <button @click="showThis">打印 this</button>



export default {

 methods: {

 showThis() {
      // this 是当前 App 组件的实例对象
      console.log(this)
 this.$refs.myh1.style.color = 'red'  //这里的myh1与上面名称对应
}

}

使用 ref 引用组件实例

如果想要使用 ref 引用页面上的组件实例 ,则可以按照如下的方式进行操作:
//子组件

<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>

//父组件中  使用ref属性  为组件添加引用名称

通过this.$refs.引用名称  可以引用组件的实力

<button @click="onReset">重置 Left 组件的 count 值为 0</button>


  <Left ref="comLeft"></Left>

  methods: {
onReset() {
      this.$refs.comLeft.resetCount()
      // this.$refs.comLeft.count = 0
    }
}

控制文本框和按钮的按需切换

通过布尔值 inputVisible 来控制组件中的文本框与按钮的按需切换
当文本框展示出来之后,如果希望它立即获得焦点,则可以为其添加 ref 引用,并调用原生 DOM 对象的 .focus() 方法即可
组件的 $nextTick(cb) 方法,会把 cb 回调 推迟到下一个 DOM 更新周期之后执行 。通俗的理解是:等组件的 DOM 更新完成之后,再执行 cb 回调函数。从而能保证 cb 回调函数可以操作到最新的 DOM 元素。

    <input type="text" v-if="inputVisible" @blur="showButton" ref="iptRef" />
    <button v-else @click="showInput">展示输入框</button>


export default {
  data() {
    return {
      // 控制输入框和按钮的按需切换;
      // 默认值为 false,表示默认展示按钮,隐藏输入框
      inputVisible: false
    }
  },

 methods: {
    // 点击按钮,展示输入框
    showInput() {
      // 1. 切换布尔值,把文本框展示出来
      this.inputVisible = true
      // 2. 让展示出来的文本框,自动获取焦点 引用this.$nextTick(cb) 方法
      this.$nextTick(() => {
        this.$refs.iptRef.focus()
      })
    },
showButton() {
      this.inputVisible = false
    }
}

复习数组中的方法

script>
    const arr = ['wr', '123', 'zs强', 'ls']

    // forEach 循环一旦开始,无法在中间被停止
    /* arr.forEach((item, index) => {
      console.log('object')
      if (item === 'zs') {
        console.log(index)
      }
    }) */

    /* arr.some((item, index) => {
      console.log('ok')
      if (item === 'zs') {
        console.log(index)
        // 在找到对应的项之后,可以通过 return true 固定的语法,来终止 some 循环
        return true
      }
    }) */
  </script>

数组 every 方法

// 需求:判断数组中,水果是否被全选了!
    const result = arr.every(item => item.state)
    console.log(result)
  </script>

数组 reduce 方法

// arr.filter(item => item.state).reduce((累加的结果, 当前循环项) => { }, 初始值)
    const result = arr.filter(item => item.state).reduce((amt, item) => amt += item.price * item.count, 0)

    console.log(result)

购物车案例

初始化项目基本结构
导入包 nmp i  会自动下载包
封装Header组件   封装props     components  导入组件     

请求数据列表

导入axios包  npm i axios -S  
在methods中定义方法 
在created周期函数中调用定义的方法

1. 调用 axios 之后,使用 async/await 进行简化

2. 使用解构赋值,从 axios 封装的大对象中,把 data 属性解构出来

3. 把解构出来的 data 属性,使用 冒号 进行重命名,一般都重命名为 { data: res }

定义一个空数组  将请求的数据赋值给数组 

if(res.meta.status === 200){
      this.list = res.message.goods
    }

导入数据渲染组件  循环渲染  自定义属性   封装渲染属性

<Goods 
    v-for="itme in list" 
    :key="itme.goods_id" 
    :title="itme.goods_name" 
    :pic="itme.goods_small_logo" 
    :price="itme.goods_price" 
    :state="itme.is_promote"
    ></Goods>

封装商品id 属性   子传父  通过id 修改对应的商品的勾选状态

 :id="itme.goods_id"
当监听到勾选状态发生改变 通过自定义事件 发送到父组组件 this.$emit(’事件名字,{id,value}')
value是更新的状态
得到子组件传过的数据后   通过 循环找到 对应的id  重新赋值
this.list.some(item =>{
        if(item.goods_id === e.id){
          item.is_promote =e.value
          return true
        }
      }

有个小问题 :点击后面商品 修改的还是第一个商品是  要修改子组件中的id

:id="'cb'+id"
 :for="'cb'+id"

Footer子组件

导入相应子组件       

全选功能 计算属性

computed: {
    fullState(){
      return this.list.every(item => item.is_promote)
    }
  },

   父传子    子组件自定义属性 绑定到父组件中

<Footer :isfull="fullState"></Footer>

点击全选   子传父   自定义事件

子组件中定义监听事件 通过$emit传

funChange(e){
      this.$emit('full-change',e.target.checked)

    }

父组件中 

 @full-change="getFullState"
//接收Footer子组件传递的全选择状态
    getFullState(val){
      
      this.list.forEach(item => (item.is_promote = val))
    }

计算勾选商品价格

1. 先 filter 过滤

 2. 再 reduce 累加

amt(){
      return this.list
      .filter(item => item.is_promote)
      .reduce((total,item) =>(total += item.goods_price * item.goods_number),0)
    }

再父向子   子组件中定义amount属性  绑定到父组件中

:amount="amt"

显示两位小数

¥{{ amount.toFixed(2) }}

商品的数量

导入counter 组件   父传子  再传子  自定义属性

// 接收商品的 id 值,将来,使用 EventBus 方案,

 // 把数量传递到 App.vue 的时候,需要通知 App 组件,更新哪个商品的数量

<Counter :num="count" :id="id"></Counter>

子传爷   用EventBus 方案 

1 、创建 eventBus.js 模块,并向外共享一个 Vue 的实例对象

2、在数据发送方绑定事件

 add(){
      const obj = {id: this.id, value: this.num + 1}
      bus.$emit('share',obj)
    }

3、在数据接收方 导入import bus from '@/components/eventBus.js'    然后再钩子函数中

 bus.$on('share', val => {
      this.list.some(item =>{
        if(item.goods_id ===val.id){
          item.goods_number = val.value
          return true
        }
      })
    }

计算勾选商品总数量

数量加

先 filter 过滤

 2. 再 reduce 累加

 total(){
      return this.list.filter(item =>item.is_promote).reduce((t,item) =>t += item.goods_number,0)
    }

得到值 父传子 自定义 all  属性   父组件绑定 

:all="total"

数量减 与加相似

sub(){
if (this.num - 1 === 0) return
      const obj = {id: this.id, value: this.num - 1}
      bus.$emit('share',obj)
    }

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值