vue3学习笔记

本文详细介绍了Vue3的准备工作,包括Vite和虚拟DOM,深入讲解组件API,如自动注册、setup用法、ref全家桶、生命周期、watch和watchEffect等。同时,文章涵盖了计算属性、hooks、浅响应式与只读数据,以及自定义ref和Provide/Inject通信机制,是Vue3学习的重要参考资料。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

vue3

准备工作

创建项目

# npm 6.x
npm init @vitejs/app vite-vue3-starter --template vue-ts

# npm 7+(需要额外的双横线)
npm init @vitejs/app vite-vue3-starter -- --template vue-ts

# yarn
yarn create @vitejs/app vite-vue3-starter --template vue-ts

注:选择项目类型为vue+ts(小tips:git bash中直接按上下键切换选择自己想要的选项,虽然界面中不会动态展示切换的用户交互过程,但是别担心,在回车后可以看到是切换到了对应选项的)

vite

Vite 通过在一开始将应用中的模块区分为 依赖源码 两类,改进了开发服务器启动时间。

支持了动态模块热重载(HMR):允许一个模块 “热替换” 它自己,而不会影响页面其余部分。

虚拟DOM

虚拟DOM就是通过JS来生成一个AST节点树(抽象语法树(AST)

  • 有key
    • 前序对比算法
    • 尾序对比算法
    • 新节点如果多出来就是挂载通过patch函数第一个参数为null
    • 旧节点如果多出来就是卸载
    • 情况特殊乱序
  • 无key patch的时候会替换
  • 乱序
    • 进行前序和后序对比算法
    • 然后进行相同的标记
    • 移除和新增

一、组件核心 API 的使用

1.组件自动注册

在 script setup 中,引入的组件可以直接使用,无需再通过components进行注册,并且无法指定当前组件的名字,它会自动以文件名为主,也就是不用再写name属性了。示例:

<template>
    <Child />
</template>

<script setup>
import Child from './Child.vue'
</script>

如果需要定义类似 name 的属性,可以再加个平级的 script 标签,在里面实现即可。

2.setup

script setup 是个啥?

它是 Vue3 的一个新语法糖,在 setup 函数中。所有 ES 模块导出都被认为是暴露给上下文的值,并包含在 setup() 返回对象中。相对于之前的写法,使用后,语法也变得更简单。

使用方式极其简单,仅需要在 script 标签加上 setup 关键字即可。示例:

<script setup></script>

setup是组合Api的入口,返回值是一个对象

setup执行时机

  • setup是在beforeCreate生命周期之前执行
  • setup在执行的时候,当前组件的实例还没有被创建出来,也就意味着:组件实例对象this根本就不能用,此时this是undefinde,不能来访问date/computed/methods/props

参数props,context

  • props参数,是一个对象,里面有父级组件向子级组件传递的数据,
  • context参数,
    • slots 对象(插槽)
    • attrs对象(获取当前标签上的所有的属性对象,但是该属性是在props中没有声明接受的所有的对象
    • emits方法(分发事件)
2.1.使用 props

通过defineProps指定当前 props 类型,获得上下文的props对象。示例:

<script setup>
  import { defineProps } from 'vue'

  const props = defineProps({
    title: String,
  })
</script>
复制代码
2.2.使用 emits

vue3.1

子组件:


<script lang="ts">
import { defineComponent } from 'vue'

export default defineComponent({
    props:{
        count:Number
    },
    setup(props,{attrs,emit,slots}) {
        const changeData = ()=>{
            emit('plus',1)
        }
        return{
            changeData
        }
    },
})
</script>
<template>
    父组件传入的参数:{{count}}
    <button v-on:click="changeData">子组件改变父组件参数</button>
</template>

父组件:

<template>
  <h1>setup和ref</h1>
  <div>count:{{count}}</div>
  <Child :canshu="count" @plus="plus"></Child>
</template>
<script lang="ts">
import { defineComponent, ref } from 'vue'
import Child from './setup-child.vue'
export default defineComponent({
  components: {
    Child
  },
  setup() {
    // return 一个对象
    const count = ref('0');
    const plus = (num:Number) => {
      count.value += num
    }
    return {
      count,
      plus
    }
  },
})
</script>

vue3.2

使用defineEmit定义当前组件含有的事件,并通过返回的上下文去执行 emit。示例:

<script setup>
  import { defineEmits } from 'vue'

  const emit = defineEmits(['change', 'delete'])
</script>
复制代码
2.3.slots (插槽)attrs

可以通过useContext从上下文中获取 slots 和 attrs。不过提案在正式通过后,废除了这个语法,被拆分成了useAttrsuseSlots。示例:

// 新3.2
<script setup>
  import { useAttrs, useSlots } from 'vue'
  const slots = useSlots()
   const attrs = useAttrs()
</script>

父组件

<template>
  <Child msg="非porps传值子组件用attrs接收" >
    <!-- 匿名插槽 -->
    <span >默认插槽</span>
    <!-- 具名插槽 -->
    <template #title>
      <h1>具名插槽</h1>
    </template>
    <!-- 作用域插槽 -->
    <template #footer="{ scope }">
      <footer>作用域插槽——姓名:{{ scope.name }},年龄{{ scope.age }}</footer>
    </template>
  </Child>
</template><script setup>
// 引入子组件
import Child from './child.vue'
</script>

子组件:

<template>
  <!-- 匿名插槽 -->
  <slot />
  <!-- 具名插槽 -->
  <slot name="title" />
  <!-- 作用域插槽 -->
  <slot name="footer" :scope="state" />
  <!-- $attrs 用来获取父组件中非props的传递到子组件的参数 -->
  <p>{{ attrs.msg == $attrs.msg }}</p>
  <!--true  没想到有啥作用... -->
  <p>{{ slots == $slots }}</p>
</template><script setup>
import { useSlots, useAttrs, reactive, toRef } from 'vue'
const state = reactive({
  name: '张三',
  age: '18'
})const slots = useSlots()
console.log(slots.default()); //获取到默认插槽的虚拟dom对象
console.log(slots.title());   //获取到具名title插槽的虚拟dom对象
// console.log(slots.footer()); //报错  不知道为啥有插槽作用域的无法获取
//useAttrs() 用来获取父组件传递的过来的属性数据的(也就是非 props 的属性值)。
const attrs = useAttrs()
</script>

4.对外暴露 setup 中的数据和方法defineExpose

传统的写法,我们可以在父组件中,通过 ref 实例的方式去访问子组件的内容,但在 script setup 中,该方法就不能用了,setup 相当于是一个闭包,除了内部的 template模板,谁都不能访问内部的数据和方法。

如果需要对外暴露 setup 中的数据和方法,需要使用 defineExpose API。示例:

<script setup>
	import { defineExpose } from 'vue'
	const a = 1
	const b = 2
	defineExpose({
	    a
	})
</script>

5.在 vue3.2 script setup 中属性和方法无需返回,直接使用!

这可能是带来的较大便利之一,在以往的写法中,定义数据和方法,都需要在结尾 return 出去,才能在模板中使用。在 script setup 中,定义的属性和方法无需返回,可以直接使用!示例:

<template>
  <div>
   	<p>My name is {{name}}</p>
  </div>
</template>

<script setup>
import { ref } from 'vue';

const name = ref('Sam')
</script>

二、ref全家桶

2.1 ref

2.1.1.把一个基本数据类型变成响应式
<template>
 <div>count:{{ count }}</div>
</template>
<script lang="ts">
import { defineComponent, ref} from 'vue'
export default defineComponent({
  setup() {
    // return 一个对象
    const count = ref('0');
    return {
      count,
    }
  },
})
</script>

2.1.2.另一个作用:可以获取页面中的元素

栗子:让输入框自动获取焦点

<template>
<h2>ref:可以获取页面中的元素</h2>
<input type="text" ref="inputRef">
</template>

<script lang="ts">
import { defineComponent, ref, onMounted, onBeforeUnmount, } from 'vue'
export default defineComponent({
    setup(){
        // 默认是空的,它加载完毕,说明组件已经存在,获取文本框元素
        const inputRef = ref<HTMLElement | null>(null)
        onMounted(()=>{
            inputRef.value && inputRef.value.focus() // 自动获取焦点
        })
        return{
            inputRef
        }
    }
})
</script>

2.2.reactive

作用:定义多个响应式数据

  • 接受一个普通对象然后返回该普通对象的响应式代理器对象,响应式转换为深层次的:会影响对象内部所有的嵌套属性
  • 返回的是一个Proxy代理对象,被代理者目标对象就是reactive中的传入对象obj
  • 内部给予ES6 的Proxy 实现。通过代理对象操作对象内部数据都是响应式的
<script lang="ts">
import { defineComponent, ref, reactive, toRefs } from 'vue';
interface Datatprops{
  rw:string[];
  selectRw:string;
  selectRwFun:(index:number)=> void
}
export default defineComponent({
  name:"app",
  setup(){
    const data: Datatprops = reactive({
      rw : ref(["萧炎","萧薰儿"]),
      selectRw : ref(""),
      selectRwFun : (index:number)=>{
        data.selectRw = data.rw[index];
      }
    })
    const refDatae = toRefs(data) // 把data作为可扩展形的
    return{
      ...refDatae,
    }
    
  }
})
</script>

<template>
  <img alt="Vue logo" src="./assets/logo.png" />
  <h1>选择初始人物</h1>  
  <button v-for="(item,index) in rw" :key="index" @click="selectRwFun(index)">{{item}}</button>
  <div>
    你选择了【{{selectRw}}】作为初始化人物
  </div>
</template>

<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>

2.3.toRefs

可以把一个响应式对象转换为普通对象,该普通对象的每一个 property 都是一个ref

就是可以使用展开运算符,而且调用时候可以直接使用属性名

<script lang="ts">
import { defineComponent, ref, reactive, toRefs, watch,} from 'vue';
interface Datatprops{
  rw:string[];
  selectRw:string;
  selectRwFun:(index:number)=> void
}
export default defineComponent({
  name:"app",
  setup(){
    const data: Datatprops = reactive({
      rw : ref(["萧炎","萧薰儿"]),
      selectRw : ref(""),
      selectRwFun : (index:number)=>{
        data.selectRw = data.rw[index];
      }
    })
    return{
      ...refDatae,
    }
  }
})
</script>

<template>
  <h1>选择初始人物</h1>  
  <button v-for="(item,index) in rw" :key="index" @click="selectRwFun(index)">{{item}}</button>
  <div>
    你选择了【{{selectRw}}】作为初始化人物
  </div>
</template>
<style>
</style>

2.4.toRef

  • 为源响应式对象上的某个属性创建一个ref对象,二者内部操作的是统一数据值,更新时二者是同步的

  • 区别ref:拷贝了一份新的数据值单独操作,更新时相互不影响

  • 应用:当要将某个prop的ref传递给复合函数时,toRef很有用

    子组件内使用useGetLength时候需要的是ref类型数据,但是传入的是number数据使用toRef(props,‘age’)就可以把number转换为ref

三、vue3生命周期

  • setup() :开始创建组件之前,在beforeCreatecreated之前执行。创建的是datamethod
  • onBeforeMount() : 组件挂载到节点上之前执行的函数。
  • onMounted() : 组件挂载完成后执行的函数。
  • onBeforeUpdate(): 组件更新之前执行的函数。
  • onUpdated(): 组件更新完成之后执行的函数。
  • onBeforeUnmount(): 组件卸载之前执行的函数。
  • onUnmounted(): 组件卸载完成后执行的函数
  • onActivated(): 被包含在<keep-alive>中的组件,会多出两个生命周期钩子函数。被激活时执行。
  • onDeactivated(): 比如从 A 组件,切换到 B 组件,A 组件消失时执行。
  • onErrorCaptured(): 当捕获一个来自子孙组件的异常时激活钩子函数(以后用到再讲,不好展现)。

执行顺序

  • 初次渲染:
  1. 父组件 – onBeforeMount
  2. 子组件 – onBeforeMount
  3. 子组件 – onMounted
  4. 父组件 – onMounted
  • 数据更新:
  1. 父组件 – onBeforeUpdate
  2. 子组件 – onBeforeUpdate
  3. 子组件 – onUpdated
  4. 子组件 – onUpdated
  • 子组件卸载:
  1. 父组件 – onBeforeUpdate
  2. 子组件 – onBeforeUnmount
  3. 子组件 – onUnmounted
  4. 父组件 – onUpdated

四、watch和watchEffect监视

4.1watch

 const overText = ref('哈哈哈哈')
 const overHandle = () =>{
     overText.value = "点餐完成|" + overText.value;
     // document.title = overText.value
 };
// watch 两个参数
//  1.监听的内容 可以是单个值也可以是数组形式
//  2.第二个是方法,第一个参数接受第一个函数的返回新值,第二个参数返回改变之前的值
// 	3.immediate默认会执行一次watch,deep深度监视
watch([overText, () => data.selectRw],(newValue, oldValue)=>{
    console.log("newValue========》",newValue);
    console.log("oldValue========》",oldValue);
    document.title = newValue[0];
}{immediate:true,deep:true})
return{
    ...refDatae,
    overText,
    overHandle,
}
// watch监听非响应式数据时候不会执行第二个参数回调 () => data.selectRw

4.2watchEffect

<script lang="ts">
import { defineComponent, ref, watchEffect } from 'vue'
export default defineComponent({
    setup() {
        const msg1 = ref<String>('第一') 
        const msg2 = ref<String>('第二') 
        const stopWatchEffect = ()=> stop() // 停止监听
        const stop = watchEffect((oninvalidate)=>{
            const input1  = document.querySelector('#input1') as HTMLInputElement
            console.log("input1",input1)
            console.log("msg1",msg1.value)
            console.log("msg2",msg2.value)
            // 清除副作用
            oninvalidate(()=>{
                console.log("before")
            })
            
        },{
            flush:"post", // 注意:这也将推迟副作用的初始运行,直到组件的首次渲染完成。
            onTrigger(e){
                debugger
            }
        })
        return{
            msg1,
            msg2,
            stopWatchEffect
        }
    },
})
</script>
<template>
    <h1>watchEffect</h1>
    <input id="input1" v-model="msg1" />
    <input v-model="msg2" />
    <button @click="stopWatchEffect">停止监听</button>
</template>

4.3watch和watchEffect的区别

1.watch可以访问新值和旧值,watchEffect不能访问。

2.watchEffect有副作用,DOM挂载或者更新之前就会触发,需要我们自己去清除副作用。

3.watch是惰性执行,也就是只有监听的值发生变化的时候才会执行,但是watchEffect不同,每次代码加载watchEffect都会执行。

4.watch需要指明监听的对象,也需要指明监听的回调。watchEffect不用指明监视哪一个属性,监视的回调函数中用到哪个属性,就监视哪个属性。

作者:赵小磊Ben
链接:https://juejin.cn/post/7032658568272691231

五、computend计算属性

import { defineComponent, ref, computed } from 'vue'
export default defineComponent({
    setup(props, ctx){
        const sentence = ref("欢迎来到王者荣耀")
		// 只传入一个回调函数,表示get
        const superSentence = computed(()=>{
            return '小明' + sentence.value
        })
        // 返回的是一个ref对象
        console.log(superSentence.value)
        return{
            
        }
    }
})
<script lang="ts">
import { computed, defineComponent, reactive, ref } from 'vue'

export default defineComponent({
    setup() {
        const user = reactive({
            name:'',
            endName:''
        })
        const username = computed({
            get(){
                return user.name + '-' + user.endName
            },
            set(val){
                console.log("e====",val)
                const names = (val as String).split('-')
                user.name = names[0]
                user.endName = names[1]
            }
        })
        return{
            user,
            username
        }

    },
})
</script>
<template>
    名:<input v-model="user.name"/>
    名:<input v-model="user.endName"/>
    姓名:<input v-model="username"/>
</template>

六、hooks

将一些公共的方法抽离出来

  • useMousePositions.ts
// 分装hooks函数
import {ref, onMounted, onBeforeUnmount, } from 'vue'

export default function(){
   const x= ref(-1)
   const y = ref(-1)
   // 点击事件的回调函数
   const clickHandler = (e:MouseEvent) =>{
      x.value = e.pageX
      y.value = e.pageY
   }
   onMounted(()=>{
      window.addEventListener('click',clickHandler)
   })
   // 组件卸载前 的生命周期
   onBeforeUnmount(()=>{
      window.removeEventListener('click',clickHandler) 
   })
   return{
      x,
      y,
   }
}
  • 引用页面
<script  lang="ts">
import { defineComponent, ref, onMounted, onBeforeUnmount, } from 'vue'
import useMousePositions from '../hooks/useMousePositions'
import useRequest from '../hooks/require'
export default defineComponent({
    setup(){
        const {x,y} = useMousePositions()
        // 发送请求
        const {loading, data, errorMsg} = useRequest('地址1')
        return{
            x,
            y,
            loading,
            data,
            errorMsg
        }
    }
})
</script>

<template>
<h2>坐标</h2>
<div>
    x:{{x}}
    y:{{y}}
</div>
<div>
    <h2 v-if="loading"> 数据加载中</h2>
    <h2 v-else-if="errorMsg">错误信息:{{errorMsg}}</h2>
    <ul v-else>
        <li>name:{{data.name}}</li>
        <li>id:{{data.id}}</li>
    </ul>
</div>
</template>

<style scoped>

</style>

七,shallowReactive(浅响应式) 和 shallowRef(不进行对象的响应式处理)

  • shallowReactive:只处理了对象最外成层响应式,也就是浅响应式(浅监视,浅劫持)

  • shallowRef:只处理了value的响应式,不进行对象的响应式处理

  • 是什么时候用浅响应式呢?

    • 一般情况下使用ref和reactive即可

    • 如果有一个对象数据,结构比较浅,但变化时候只是外层属性变化 ====》 shallowReactive

    • 如果有一个对象数据,后面会产生新的对象来替换 ===》 shallowRef

八、readonly(深度只读) 和shallowReadonly(浅只读)

  • readonly
    • 深度只读
    • 获取一个对象(响应式或者纯对象)或ref并返回原始代理的只读代理
    • 只读代理是深层的:访问的任何嵌套property也是只读的
  • shallowReadonly
    • 浅只读数据
    • 创建一个代理,使其自身的property为只读,但是不执行嵌套对象的深度只读转换(深层次对象还是可以修改的)
  • 应用场景:
    • 在某些特定情况下,我们可能不许忘对数据进行更新的操作,那就可以包装成一个只读代理对象来读取数据,而不能修改或者是删除
<script  lang="ts">
import { defineComponent, ref, onMounted, reactive, onBeforeUnmount, readonly, shallowReadonly, } from 'vue'
export default defineComponent({
    setup(){
        // 默认是空的,它加载完毕,说明组件已经存在,获取文本框元素
        const state = reactive({
            name:'佐伊',
            age:'200',
            car:{
                name:'奔驰',
                color:'yellow'
            }
        })
        // 只读数据 -- 深层只读
        // const state2 = readonly(state)
        // 只读数据 -- 浅只读(只有第一层只读)
        const state2 = shallowReadonly(state)
        const update = () =>{
            console.log('ceshi')
            state2.car.name += 2
        }
        return{
            state,
            update
        }
    }
})
</script>

<template>
<hr/>
{{state}}
<hr/>
<button @click="update"> 更新数据</button>
</template>

<style scoped>

</style>

九、toRow 与 markRaw

  • toRaw(转换成普通的对象)
    • 返回由reactivereadonly方法转换为响应式代理的普通对象.
    • 这是一个还原方法,可用于临时读取,访问不会被dialing/跟踪,写入时也不会触发界面更新。
  • markRaw
    • 标记一个对象,时期用原不会转换为代理,返回对象本身
    • 应用场景:
      • 有些值不应被设置为响应式,例如负责的第三类实力或Vue组件对象。
      • 当渲染具有不可变数据源的大列表时,跳过代理转换可以提高性能

十.customRef

customRed用于自定义一个ref,可以显式的控制一来最终和触发响应,接受一个工厂函数,俩格参数分别用于最终的track喻用于触发响应的trigger,并返回一个带有getset属性的对象。

  • 使用自定义ref实现带防抖功能的v-model;
<template>
    <h2>CustomRef的使用</h2>
    <input type="text" v-model="keyword"><br />
    {{keyword}}
</template>

<script lang="ts">
import { customRef, defineComponent, ref } from 'vue'

// 自定义hook防抖函数
function useDebouncedRef<T>(value: T, delay = 200) {
    let timeOutId: number
    // 自定义ref对象
    return customRef((track, trigger) => {
        return {
            // 返回数据
            get() {
                // 追踪数据
                track()
                return value
            },
            // 设置数据
            set(newValue: T) {
                clearTimeout(timeOutId)
                timeOutId = setTimeout(() => {
                    value = newValue
                    trigger()
                }, delay)
            },
        }
    })
}
export default defineComponent({
    name: 'App',
    setup() {
        const keyword = useDebouncedRef('abc', 500)
        return {
            keyword,
        }
    },
})
</script>

十一.Provide 和 inject多级通信

父子组件之间的通信或者父级直接与孙子组件通信

父级:

  setup(){
        // 响应式数据
        const color = ref('red')
        // 提供数据
        provide('color',color)
         return{
            color
         }
    }

孙子:

 setup(){
        // 注入
        const color = inject('color')
         return{
             color
         }
    }
<think>嗯,用户想了解Excel中的VLOOKUP函数的用法和参数含义。首先,我需要回忆一下VLOOKUP的基本结构。VLOOKUP是垂直查找函数,用于在表格的首列查找指定的值,然后返回该行中指定列的数据。它的四个参数分别是查找值、表格范围、列索引号和匹配模式。 接下来,我得确认每个参数的具体作用。第一个参数是lookup_value,也就是用户要查找的值,比如产品ID或者姓名。第二个参数是table_array,即查找的范围,这里要注意的是,查找值必须位于这个范围的第一列,否则函数无法正确工作。第三个参数是col_index_num,也就是用户想要返回的数据在表格范围中的第几列,这个列数是从表格范围的第一列开始算起的,不是整个工作表的列。第四个参数是range_lookup,决定是精确匹配还是近似匹配,通常用FALSE或0来指定精确匹配,避免错误。 然后,用户可能需要一个具体的例子来理解如何使用。比如,假设有一个产品价格表,用户想根据产品ID查找对应的价格。这时候,VLOOKUP就可以在ID列查找,然后返回价格列的数据。同时,要提醒用户注意表格范围最好使用绝对引用,比如$A$2:$C$100,这样在拖动公式时范围不会变化。 可能遇到的问题也需要考虑。比如,如果查找值不在表格的第一列,或者列索引号超过了表格的列数,函数会返回错误。此外,数据格式不一致也可能导致问题,比如查找值是数字,而表格中是文本格式的数字,这时候需要统一格式。还有,当出现#N/A错误时,可能是查找值不存在,或者匹配模式设置不正确,需要检查参数是否正确。 用户可能还会问到如何避免常见的错误,比如部分数据匹配出错的情况。这时候需要检查是否有多余的空格,或者数据格式不一致,或者表格范围没有锁定导致拖动时偏移。此外,XLOOKUP作为VLOOKUP的升级版,可能在某些情况下更方便,比如可以向左查找或者返回多列数据,这也是可以提及的内容。 最后,整理步骤,从基础语法到参数说明,再到具体案例,逐步引导用户理解如何使用VLOOKUP函数。同时,提供常见错误和解决方法,帮助用户在实际应用中避免问题。如果有必要,还可以比较VLOOKUP和其他查找函数的区别,比如HLOOKUP或XLOOKUP,但根据用户的问题,主要集中在VLOOKUP本身即可。</think>### Excel VLOOKUP函数详解 #### 一、基础语法与参数说明 VLOOKUP函数的语法为: $$=VLOOKUP(lookup\_value, table\_array, col\_index\_num, [range\_lookup])$$ 包含4个参数: 1. **lookup_value**(必填):要查找的值(如单元格引用或具体值) 2. **table_array**(必填):包含数据的表格范围(必须包含查找列和返回列) 3. **col_index_num**(必填):返回值所在列的序号(从table_array第一列开始计数) 4. **range_lookup**(可选):匹配类型 - `TRUE`/`1`:近似匹配(默认值,需数据升序排列) - `FALSE`/`0`:精确匹配(常用选项) [^1][^2] #### 二、使用步骤演示(工资表查询案例) 假设需要根据员工编号查询工资: 1. 建立查询单元格(如`B12`) 2. 输入公式: ```excel =VLOOKUP(A12, $A$2:$D$100, 4, 0) ``` - `A12`:待查询的员工编号 - `$A$2:$D$100`:锁定数据区域(绝对引用) - `4`:返回第4列(工资列) - `0`:精确匹配 [^2][^3] #### 三、常见错误与解决方法 | 错误现象 | 原因 | 解决方案 | |---------|------|---------| | #N/A | 查找值不存在 | 检查数据源或改用`IFERROR`容错 | | #REF! | 列序号超出范围 | 确认col_index_num ≤ 表格列数 | | 部分匹配失败 | 数据格式不一致 | 统一数值/文本格式 | | 结果错位 | 表格未锁定 | 使用`$`符号固定区域引用 | [^3][^4] #### 四、进阶技巧 1. **多条件查询**: 使用辅助列合并多个条件字段 ```excel =VLOOKUP(A2&B2, $D$2:$F$100, 3, 0) ``` 2. **通配符匹配**: `"*"`匹配任意字符,`"?"`匹配单个字符 ```excel =VLOOKUP("张*", $A$2:$C$100, 3, 0) ``` 3. **跨表查询**: 引用其他工作表数据 ```excel =VLOOKUP(A2, Sheet2!$A$2:$D$100, 4, 0) ``` [^1][^4]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值