ref 引用 & 数组方法

目录

ref 引用

获取 DOM 元素

引用组件实例

初步实现按钮和文本框的按需展示

this.$nextTick 的应用场景

updated 不可用的原因

数组方法

some 循环

foreach 循环

some 循环

every 循环

reduce 基本用法

reduce 简化写法


jQuery 简化了程序员操作 DOM 的过程

在 vue 中,程序员不需要操作 DOM,只需要将数据维护好即可。即数据驱动视图

在 vue 项目中,不建议安装和使用 jQuery

当 vue 项目中,需要进行 DOM 操作时,则需要拿到页面上某个 DOM 元素的引用

ref 引用

用来辅助开发者在不依赖于 jQuery 的情况下,获取 DOM 元素或组件的引用

每一个 vue 的组件实例上,都包含一个 $refs 对象,里面存储着对应的 DOM 元素或组件的引用

默认情况下,组件的 $refs 指向一个空对象

获取 DOM 元素

  • 通过 ref 指定的引用名,可以获取 dom 元素
  • ref 指定的引用名必须唯一,类似于 id 选择器
<template>
  <div class="app-container">
    <!-- 通过 ref 指定的引用,可以获取 dom 元素 -->
    <!-- 相当于 id 或者 class 等选择器 -->
    <!-- ref 指定的引用名不能重名,类似于 id 选择器 -->
    <h1 ref="myh1">App 根组件</h1>
    <button @click="showThis">打印 this</button>
  </div>
</template>

<script>
    export default {
        methods: {
            showThis() {
                // this 是当前 app 组件的实例对象
                // console.log(this.$refs.myh1);
                this.$refs.myh1.style.color = 'red';
            }
        },
    }
</script>

引用组件实例

  • 在 App.vue 组件中,对 Left 组件标签设置 ref 引用,即可通过 App.vue 组件的 this 获取  Left.vue 中的实例对象,进而获取组件的数据和方法
<!-- 被引用组件 Left.vue -->
<template>
  <div class="left-container">
    <h3>Left 组件 --- {{ count }}</h3>
    <button @click="count++">+1</button>
    <button @click="resetCount">重置</button>

  </div>
</template>

<script>
    export default {
        data() {
            return {
                count: 0,
            }
        },
        methods: {
            resetCount() {
                this.count = 0;
            }
        },
    }
</script>
<template>
  <div class="app-container">
    <h1>App 根组件</h1>
    <button @click="showThis">打印 this</button>
    <button @click="onReset">重置 Left 组件的 count 值</button>
    <hr />

    <div class="box">
      <!-- 渲染 Left 组件和 Right 组件 -->
      <!-- 当组件标签添加 ref 引用之后,即可通过 app.vue 的 this 获取该组件标签所代表的组件的实例对象 -->
      <Left ref="comLeft"></Left>
    </div>
  </div>
</template>

<script>
    import Left from "@/components/Left.vue"
    export default {
        methods: {
            // 点击按钮,重置 Left 组件的 count 值
            onReset() {
                // this.$refs.comLeft.resetCount();
                this.$refs.comLeft.count = 0;
            }

        },
        components: {
            Left,
        }
    }
</script>

初步实现按钮和文本框的按需展示

<template>
  <div class="app-container">
    <!-- @blur 失去焦点,展示按钮 -->
    <input type="text" v-if="inputVisible" @blur="showButton">
    <button v-else @click="showInput">展示输入框</button>
  </div>
</template>

<script>
    export default {
        data() {
            return {
                // 控制输入框和按钮的按需展示
                // 默认值为 false,表示默认展示按钮,隐藏输入框
                inputVisible: false,
            }
        },
        methods: {
            // 点击按钮,展示输入框
            showInput() {
                this.inputVisible = true;
            },
            showButton() {
                this.inputVisible = false;
            }
        },
    }
</script>

this.$nextTick 的应用场景

  • 上述案例中,为了让文本框展示后自动获得焦点
  • 当数据发生改变时,该数据并没有立刻渲染到 DOM 结构中,此时使用更新后的某些 DOM 元素的引用将会报错(因为此时该元素还未被渲染到 DOM 结构中)
  • 组件的 $nextTick(cb) 方法,会把 cb 回调推迟到下一个 DOM 更新周期之后执行
  • 通俗的理解是:等组件的 DOM 更新完成之后(updated 之后),再执行 cb 回调函数
  • 从而保证 cb 回调函数可以操作到最新的 DOM 元素
<template>
  <div class="app-container">
    <!-- 引用名最好以 Ref 结尾,维护较方便 -->
    <input type="text" v-if="inputVisible" @blur="showButton" ref="iptRef">
    <button v-else @click="showInput">展示输入框</button>
  </div>
</template>

<script>
    export default {
        methods: {
            // 点击按钮,展示输入框
            showInput() {
                // 切换 boolean 值,让文本框展示出来
                this.inputVisible = true;
                // 这行代码执行完毕之后,页面还未更新,文本框将要却还没有展示出来
                // 页面上看到的还是 button,input 还未展示
                // 因此 iptRef 还处于 undefined 
                // this.$refs.iptRef.focus();
                // console.log(this.$refs.iptRef); // undefined
                this.$nextTick(() => {
                    this.$refs.iptRef.focus();
                });
            },
        },
    }
</script>

updated 不可用的原因

  • 在上述场景中,点击之后,相应的 DOM 元素发生改变
  • 是在特定条件下发生的
  • 而 updated 只要数据发生改变就会自动触发
  • 生命周期函数必须和 data、methods 平级
<script>
    export default {
        updated() {
          this.$nextTick(() => {
             this.$refs.iptRef.focus();
          });
        },
    }
</script>

updated 在数据发生改变时必被触发,当 inputVisible 值改变为 true 之时,updated 随数据的改变而被触发,文本框展示,自动获得焦点

当我们将鼠标移开之后,本应将文本框隐藏,按钮展示。但此时,inputVisible 的值再次发生改变,此时 updated 再次被触发,自动获得焦点。这与我们原本的设定发生矛盾,程序报错

数组方法

some 循环

foreach 循环

  • foreach 循环只要开始,即使找到了目标元素,也不会中途终止循环,而是会继续将循环执行完毕
    <script>
        const arr = ["关羽", "张飞", "赵云", "马超", "黄忠"];
        // foreach 循环只要开始,即使找到目标元素,还会继续将循环执行完毕
        // 效率较差
        arr.forEach((item, index) => {
            console.log('ok');
            if (item === '张飞') {
                console.log(index);
            }
        });
    </script>

some 循环

  • some 循环在找到目标元素之后,通过 return true; 固定语法可以立刻终止循环
    <script>
        const arr = ["关羽", "张飞", "赵云", "马超", "黄忠"];
        arr.some((item, index) => {
            console.log('ok');
            if (item === '张飞') {
                console.log(index);
                // 找到目标元素之后,通过 return true 终止 some 循环
                // return true; 固定写法
                return true;
            }
        });
    </script>

every 循环

  • 只有当数组中的每一项都满足条件时,才返回 true;否则返回 false
    <script>
        const arr = [{
            id: '1',
            name: '张三',
            state: true
        }, {
            id: '2',
            name: '张四',
            state: true
        }, {
            id: '3',
            name: '张五',
            state: false,
        }, ];
        // every 循环:只有数组中的每一项都满足要求,返回 true
        // 只要有一项不满足要求,返回 false 
        // 判断数组中所有的项是否都被选中
        const result = arr.every(item => item.state);
        console.log(result);
    </script>

reduce 基本用法

    <script>
        // reduce 语法
        arr.filter(item => item.state).reduce((累加结果, 当前循环项) => {}, 初始值);
    </script>
    <script>
        const arr = [{
            id: '1',
            name: '香蕉',
            state: true,
            price: 3,
            count: 1
        }, {
            id: '2',
            name: '苹果',
            state: true,
            price: 8,
            count: 2
        }, {
            id: '3',
            name: '西瓜',
            state: false,
            price: 2,
            count: 3
        }, ];

        // 把购物车中已选中的水果(state=true),总价累加起来
        // let amt = 0; // 总价
        // arr.filter(item => item.state).forEach(item => {
        //     amt += item.price * item.count;
        // });
        // console.log(amt);

        // reduce 方法 
        // arr.filter(item => item.state).reduce((累加结果, 当前循环项) => {}, 初始值);
        const result = arr.filter(item => item.state).reduce((amt, item) => {
            return amt += item.price * item.count;
        }, 0);
        console.log(result);
    </script>

reduce 简化写法

    <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);
    </script>
  • 21
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在Vue中使用ref创建一个二维数组方法是,在Vue3的原型链中使用const arr = ref([[]])来定义一个二维数组。然后在给二维数组赋值时需要在每一行新创建一个数组。例如,可以使用arr.value[i] = ref([])来创建一维数组,并使用arr.value[i].value[j] = 1来给二维数组赋值。这样可以确保在使用二维数组时不会出现错误。 在Vue2中,使用const arr = [[]]来定义一个二维数组,并使用arr[i] = []来创建一维数组,然后使用arr[i][j] = 1来给二维数组赋值。同样,这样的操作也能够实现二维数组的使用。&lt;span class=&quot;em&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;em&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;em&quot;&gt;3&lt;/span&gt; #### 引用[.reference_title] - *1* *2* [vue3和vue创建二维数组的不同](https://blog.csdn.net/qq_28866895/article/details/124340794)[target=&quot;_blank&quot; data-report-click={&quot;spm&quot;:&quot;1018.2226.3001.9630&quot;,&quot;extra&quot;:{&quot;utm_source&quot;:&quot;vip_chatgpt_common_search_pc_result&quot;,&quot;utm_medium&quot;:&quot;distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2&quot;}}] [.reference_item style=&quot;max-width: 50%&quot;] - *3* [前端vue二维数组接口渲染](https://blog.csdn.net/weixin_52164116/article/details/121662804)[target=&quot;_blank&quot; data-report-click={&quot;spm&quot;:&quot;1018.2226.3001.9630&quot;,&quot;extra&quot;:{&quot;utm_source&quot;:&quot;vip_chatgpt_common_search_pc_result&quot;,&quot;utm_medium&quot;:&quot;distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2&quot;}}] [.reference_item style=&quot;max-width: 50%&quot;] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值