首页 > 其他分享 >【iOS】KVC

【iOS】KVC

时间:2024-09-22 17:51:05浏览次数:3  
标签:key KVC iOS value NSString NSNumber 方法

文章目录

KVC的定义

容器类中KVC的实现

KVC设值

KVC取值

KVC使用KeyPath

KVC处理异常

KVC处理设值nil异常

KVC处理UndefinedKey异常

KVC处理数值和结构体类型属性

KVC键值验证

KVC处理集合

简单集合运算符

对象运算符

KVC处理字典

KVC应用

动态地取值和设值

用KVC来访问和修改私有变量

Model和字典转换

修改一些控件的内部属性

操作集合

用KVC实现高阶消息传递

实现KVO

KVC的定义

定义:KVC(Key-value coding)键值编码,是指iOS开发中,允许开发者通过key名直接访问对象的属性,或者给对象的属性赋值,而不需要调用明确的存取方法。使用KVC键值编码的好处就是可以在运行时动态地访问和修改对象的属性,而不是在编译时确定。

注意:在实现了访问器方法的类中,使用点语法和KVC访问对象差别不大,二者可以混用。但是在没有访问器方法的类中,无法使用点语法,这时KVC就有优势了。

KVC的定义都是对NSObject的扩展来实现的,OC语言中有一个显示的NSKeyValueCoding类别名,所以所有继承了NSObject的类型,都能使用KVC(一些没有继承NSObject的纯Swift类和结构体不支持KVC),下面是KVC最重要的四个方法:

- (nullable id)valueForKey:(NSString *)key;//直接通过Key来取值
- (void)setValue:(nullable id)value forKey:(NSString *)key;//通过Key来取值
- (nullable id)valueForKeyPath:(NSString *)keyPath;//通过KeyPath来取值
- (void)setValue:(nullable id)value forKeyPath:(NSString *)keyPath;//通过KeyPath来设值

此外,在NSKeyValueCoding这个类别中,还有一些其他的方法:

+ (BOOL)accessInstanceVariablesDirectly;
//默认返回YES,表示如果没有找到Set<Key>这个存取方法的话,会按照_key, _iskey, key, iskey的顺序搜索成员,重写方法设置成返回NO就不会这样搜索,也就是说如果没找到Set<Key>这个方法,就不会再继续搜索
- (BOOL)validateValue:(inout id __nullable * __)ioValue forKey:(NSString *)inKey error:(out NSError **)outError;
//KVC提供属性值正确性验证的API,可以用来检查set的值是否正确,为不正确的值做一个替换值或者拒绝设置新值并返回错误原因(通过outError参数来返回错误原因)
- (NSMutableArray *)mutableArrayValueForKey:(NSString*)key;
//集合操作的API,如果属性是一个NSMutableArray,那么可以用这个方法来返回这个NSMutableArray,在类别里面还有类似的API来对set操作
- (nullable id)valueForUndefinedKey:(NSString *)key;
//如果key不存在,且KVC无法搜索到任何和key有关的字段或属性,则会调用这个方法,默认抛出异常
- (void)setValue:(nullable id)value forUndefinedKey:(NSString *)key;
//这个方法也是针对key不存在的情况进行的操作,不过这个方法是在设值时操作
- (void)setNilValueForKey:(NSString *)key;
//如果在SetValue时,为方法传入的参数是nil(也就是说给Value传一个nil),就会调用这个方法
- (NSDictionary<NSString *, id> *)dictionaryWithValuesForKeys:(NSArray<NSString *> *)keys;
//输入一组key,返回该组key对应的value,再转回字典返回

关于validateValue:ioValue forKey:in**Key error:outError 这个方法,这里给出一个使用的示例,可以使用这个方法来对设置的属性值进行验证,这里以验证是否为空为例

首先在自定义的类中实现这个方法:

- (BOOL)validateValue:(inout id __nullable *)ioValue forKey:(NSString *)inKey error:(out NSError **)outError {
    // 检查键名
    if ([inKey isEqualToString:@"name"]) {
        NSString *name = (NSString *)*ioValue;
        
        // 验证值是否为空
        if (name.length == 0) {
            if (outError) {
                *outError = [NSError errorWithDomain:@"MyDomain"
                                                  code:1001
                                              userInfo:@{NSLocalizedDescriptionKey: @"Name cannot be empty."}];
            }
            return NO; // 验证失败
        }
    }
    
    return YES; // 验证成功
}

然后在设置属性值时,调用此方法进行验证:

NSError *error = nil;
NSString *name = @"";
if (![self validateValue:&name forKey:@"name" error:&error]) {
    NSLog(@"Validation failed: %@", error.localizedDescription);
} else {
    self.name = name; // 设置有效的值
}

容器类中KVC的实现

在自定义容器类时,KVC有特殊的实现

苹果原生的容器类比如NSArray或者NSSet等,都已经实现了对应的方法。

对于有序集合:

-countOf<Key> //必须实现,对应NSArray的方法count:
-objectIn<Key>AtIndex: -<Key>AtIndexes: //这两个方法必须实现一个,对应NSArray的方法objectAtIndex: 和objectsAtIndexes:
-get<Key>:range: //不是必须实现,对应NSArray方法getObjects:range:
-insertObject:in<Key>AtIndex: -insert<Key>:atIndexes: //两个必须实现一个,类似NSMutableArray的方法insertObject: atIndex: 和insertObjects: atIndexes:
-replaceObejctIn<Key>AtIndex: withObject:
-replace<Key>AtIndexes: with<Key>://可选的,是一种替换元素的方法

对于无序集合:

-countOf<Key> //必须实现,对应NSSet
-objectIn<Key>AtIndex: //由于NSSet是无序的,此方法可以选择性实现
-<Key>AtIndexes: //和上一个方法一样,选择性实现
-get<Key>: range: //不是必须实现,对应NSArray的getObjects: range:方法,无序一般不适用
-insertObject:in<Key>AtIndex: //无序集合一般不支持索引插入
-insert<Key>:atIndexes: //和上一个方法一样
-removeObjectFrom<Key>AtIndex: //和前两个一样
-remove<Key>AtIndexes: //和之前一样
-replaceObejctIn<Key>AtIndex: withObject:
-replace<Key>AtIndexes: with<Key>: //都和之前一样

一上就是KVC的定义和KVC有关的一些方法

KVC设值

通过KVC设值时,会在对象中寻找对应的key,当调用setValue: forKey:时,有一个寻找key的顺序:

  • 优先调用setKey: ,通过setter方法完成设置。

  • 如果未找到setKey:方法,会先检查+ (BOOL)accessInstanceVariablesDirectly方法有没有返回YES,默认返回YES,如果重写该方法返回NO的话,那么这一步KVC会执行setValue: forUndefinedKey: 方法。如果返回YES,会在该类里面搜索有没有名为_key的成员变量,无论该变量是在类接口定义,还是在实现处定义,也无论使用什么修饰关键字。

  • 如果没有setKey:方法,也没有_key成员变量,就会搜索 _isKey成员的变量。

  • 如果以上都没有,就会继续搜索Key和isKey的成员变量

  • 如果方法和相应成员变量全都不存在,就会执行setValue: forUndefinedKey: 方法,默认抛出异常

简单来说:如果没有找到SetKey方法,会按照_Key, _isKey,Key,isKey的顺序搜索成员并进行赋值操作。

来尝试一下寻找_Key的成员变量

@interface KVCMethod : NSObject {
    NSString* _FirstName;
}
@end
  
  int main(int argc, char * argv[]) {
    NSString * appDelegateClassName;
    @autoreleasepool {
        KVCMethod* kvcMethod = [[KVCMethod alloc] init];
        [kvcMethod setValue:@"李" forKey:@"FirstName"];
        NSLog(@"%@", [kvcMethod valueForKey:@"FirstName"]);
        }
        appDelegateClassName = NSStringFromClass([AppDelegate class]);
    }
    return UIApplicationMain(argc, argv, nil, appDelegateClassName);
}
​

这里将后续的代码删去了,所以只用看第一行输出的结果,可以看到运行的结果是成功找到了_key成员变量并且成功设置和取出了相应的成员变量

再将accessInstanceVariablesDirectly设置为NO运行:

我们重写处理异常的方法来检查修改accessInstanceVariablesDirectly的返回值之后程序是怎么执行的

@implementation KVCMethod
​
- (BOOL)validateValue:(inout id  _Nullable __autoreleasing *)ioValue forKey:(NSString *)inKey error:(out NSError *__autoreleasing  _Nullable *)outError {
    if ([inKey isEqualToString:@"name"]) {
        NSString* name = (NSString*)*ioValue;
        if (name.length == 0) {
            if (outError) {
                *outError = [NSError errorWithDomain:@"MyDoain" code:1001 userInfo:@{NSLocalizedDescriptionKey: @"Name cannot be empty"}];
            }
            return NO;
        }
    }
    return YES;
}
​
+ (BOOL)accessInstanceVariablesDirectly {
    return NO;
}
​
- (id)valueForUndefinedKey:(NSString *)key {
    NSLog(@"出现异常,不存在该key:%@", key);
    return nil;
}
​
- (void)setValue:(id)value forUndefinedKey:(NSString *)key {
    NSLog(@"出现异常,不存在该key:%@", key);
}
​
@end

运行结果如下:

可以发现触发了处理异常的方法,也就是说程序没有按照之前的顺序寻找成员变量,也就没有成功赋值,程序输出NULL

KVC取值

当调用valueForKey: @"name"的代码时,KVC对key的都搜索方式不同于setValue: forKey: ,其搜索方式如下:

  • 首先按照getKey,Key,isKey的顺序查找getter方法,找到的话会直接调用。如果是BOOL或者int等值类型,会将其包装成一个NSNumber对象

  • 如果没有找到getter方法,就会查找countOf,objectIn AtIndex 或者AtIndexes 格式的方法,如果其中一个被找到,就会返回一个可以相应NSArray所有方法的代理集合(NSKeyValueArray,属于NSArray的子类),调用这个代理集合的方法或者说给它发送属于NSArray的方法,就会以countOf,objectIn Atindex或AtIndexes这几个方法组合的形式调用。

  • 如果上面方法都没有找到,就会同时查照countOf,enumeratorOf,merberOf格式的方法,这三个方法都找到了的话,那么就返回一个可以相应NSSet所有方法的代理集合,和上面所说一样,给这个代理集合发送NSSet的方法,就会以countOf,enumeratorOf,merberOf组合的形式调用。

  • 如果还没有找到,这时候就会检查方法accessInstanceVariablesDirectly的返回值,如果是YES,就会按照之前设值一样的顺序,搜索_Key, _isKey,Key,isKey。

KVC使用KeyPath

当自定义类的成员变量是自定义类或者其他的复杂数据类型时,可以先使用KVC获取该属性,然后再用一次KVC获得这个属性的属性。但这种方法比较繁琐,KVC有一种更简洁的方法,那就是键路径KeyPath,按照路径寻找Key

- (nullable id)valueForKeyPath:(NSString *)keyPath;                  //通过KeyPath来取值
- (void)setValue:(nullable id)value forKeyPath:(NSString *)keyPath;  //通过KeyPath来设值
int main(int argc, char * argv[]) {
    NSString * appDelegateClassName;
    @autoreleasepool {
        KVCMethod* kvcMethod = [[KVCMethod alloc] init];
        SubKVCMethod* subKVCMethod = [[SubKVCMethod alloc] init];
        [kvcMethod setValue:subKVCMethod forKey:@"subKVCMethod"];
        [kvcMethod setValue:@"南崩" forKeyPath:@"subKVCMethod.name"];
        NSLog(@"KVCMethod的属性SubKVCMethod的属性name是%@", [kvcMethod valueForKeyPath:@"subKVCMethod.name"]);
        }
        appDelegateClassName = NSStringFromClass([AppDelegate class]);
    }
    return UIApplicationMain(argc, argv, nil, appDelegateClassName);
}

运行的结果是:

发现成功实现了赋值和取值操作,并且这里KeyPath的格式其实就类似于我们点语法的格式

KVC处理异常

之前其实已经提到过KVC处理异常的方法了,这里主要是两种异常,一种是使用了错误的Key,另一种是设值时传递了nil的值,分别可以使用两类方法来处理

KVC处理设值nil异常

KVC一般不允许在调用setValue: forKey: 时传递一个nil的值。如果传入一个nil的值,KVC会调用setNilValueForKey:方法,这个方法默认抛出异常。

#import "KVCMethod.h"
​
@implementation KVCMethod
​
- (void)setNilValueForKey:(NSString *)key {
    NSLog(@"不能将%@设成nil", key);
}
​
@end

KVC处理UndefinedKey异常

当调用setValue: forKey或者valueForKey时,一般不允许使用不存在的Key,否则会报错forUndefinedKey发生崩溃,重写forUndefinedKey可以避免崩溃

@implementation KVCMethod
​
- (id)valueForUndefinedKey:(NSString *)key {
    NSLog(@"出现异常,不存在该key:%@", key);
    return nil;
}
​
- (void)setValue:(id)value forUndefinedKey:(NSString *)key {
    NSLog(@"出现异常,不存在该key:%@", key);
}
​
@end

KVC处理数值和结构体类型属性

valueForKey: 方法总是会返回一个id对象,如果原本的变量类型是值类型或者结构体,返回值会封装成NSNumber或者NSValue对象,这两个类会处理数字、布尔值、指针和结构体。

在使用setValue: forKey时,必须手动将值类型转换成NSNumber或者NSValue类型,才能传递过去,因为传递进去和取出来的都是id类型,所以需要自己确保类型正确性,运行时如果类型错误会抛出异常

@interface KVCMethod : NSObject
​
@property(nonatomic, readwrite, assign)int age;
​
@end
int main(int argc, char * argv[]) {
    NSString * appDelegateClassName;
    @autoreleasepool {
        KVCMethod* kvcMethod = [[KVCMethod alloc] init];
        [kvcMethod setValue:[NSNumber numberWithInt:23] forKey:@"age"];
        NSLog(@"age = %@", [kvcMethod valueForKey:@"age"]);
        appDelegateClassName = NSStringFromClass([AppDelegate class]);
    }
    return UIApplicationMain(argc, argv, nil, appDelegateClassName);
}
​

这里就是为类添加了一个int类型的属性age,我们赋给age的是一个NSNumber对象,KVC会自动的将NSNumber对象转换成int对象,然后再调用相应的访问器方法设置age的值。

使用valueForKey:方法时,返回的值是一个NSNumber。

需要注意的是,我们不能直接将数值通过KVC赋值,需要先转换为NSNumber和NSValue类型,那么哪些类型用NSNumber封装,哪些用NSValue呢?

可以使用NSNumber的数据类型:

+ (NSNumber*)numberWithChar:(char)value;
+ (NSNumber*)numberWithUnsignedChar:(unsignedchar)value;
+ (NSNumber*)numberWithShort:(short)value;
+ (NSNumber*)numberWithUnsignedShort:(unsignedshort)value;
+ (NSNumber*)numberWithInt:(int)value;
+ (NSNumber*)numberWithUnsignedInt:(unsignedint)value;
+ (NSNumber*)numberWithLong:(long)value;
+ (NSNumber*)numberWithUnsignedLong:(unsignedlong)value;
+ (NSNumber*)numberWithLongLong:(longlong)value;
+ (NSNumber*)numberWithUnsignedLongLong:(unsignedlonglong)value;
+ (NSNumber*)numberWithFloat:(float)value;
+ (NSNumber*)numberWithDouble:(double)value;
+ (NSNumber*)numberWithBool:(BOOL)value;
+ (NSNumber*)numberWithInteger:(NSInteger)valueNS_AVAILABLE(10_5,2_0);
+ (NSNumber*)numberWithUnsignedInteger:(NSUInteger)valueNS_AVAILABLE(10_5,2_0);

可以使用NSValue的数据类型:

+ (NSValue*)valueWithCGPoint:(CGPoint)point;
+ (NSValue*)valueWithCGSize:(CGSize)size;
+ (NSValue*)valueWithCGRect:(CGRect)rect;
+ (NSValue*)valueWithCGAffineTransform:(CGAffineTransform)transform;
+ (NSValue*)valueWithUIEdgeInsets:(UIEdgeInsets)insets;
+ (NSValue*)valueWithUIOffset:(UIOffset)insetsNS_AVAILABLE_IOS(5_0);

NSValue主要用于处理结构体类型的数据,任何结构体都可以转化成NSValue对象,包括自定义的结构体

KVC键值验证

KVC有提供验证Key对应的Value是否合法的方法:

- (BOOL)validateValue:(inoutid*)ioValue forKey:(NSString*)inKey error:(outNSError**)outError;

这个方法在KVC的定义那个部分已经有过讲解,这里就不多赘述了。

KVC处理集合

简单集合运算符

简单集合运算符有@avg, @count,@max,@min,@sum5种,这五种运算符分别表示平均值,总个数,最大值,最小值和总量

int main(int argc, char * argv[]) {
    NSString * appDelegateClassName;
    @autoreleasepool {
        KVCMethod* kvcMethod1 = [[KVCMethod alloc] init];
        kvcMethod1.name = @"灰灰";
        kvcMethod1.age = 12;
        KVCMethod* kvcMethod2 = [[KVCMethod alloc] init];
        kvcMethod2.name = @"黑黑";
        kvcMethod2.age = 22;
        KVCMethod* kvcMethod3 = [[KVCMethod alloc] init];
        kvcMethod3.name = @"白白";
        kvcMethod3.age = 32;
        
        NSArray* array = [NSArray arrayWithObjects:kvcMethod1, kvcMethod2, kvcMethod3, nil];
        NSNumber* sum = [array valueForKeyPath:@"@sum.age"];
        NSLog(@"sum = %@", sum);
        NSNumber* avg = [array valueForKeyPath:@"@avg.age"];
        NSLog(@"avg = %@", avg);
        NSNumber* count = [array valueForKeyPath:@"@count.age"];
        NSLog(@"count = %@", count);
        NSNumber* min = [array valueForKeyPath:@"@min.age"];
        NSLog(@"min = %@", min);
        NSNumber* max = [array valueForKeyPath:@"@max.age"];
        NSLog(@"max = %@", max);
        appDelegateClassName = NSStringFromClass([AppDelegate class]);
    }
    return UIApplicationMain(argc, argv, nil, appDelegateClassName);
}

对象运算符

以数组的形式返回指定内容,有两种:

@distinctUnionOfObjects

@unionOfObjects

他们的返回值都是NSArray,区别是前者返回元素唯一,是去重后的结果,后者返回全集。

KVC处理字典

有两个关于NSDictionary的方法:

- (NSDictionary<NSString *, id> *)dictionaryWithValuesForKeys:(NSArray<NSString *> *)keys;
- (void)setValuesForKeysWithDictionary:(NSDictionary<NSString *, id> *)keyedValues;

第一个方法是指输入一组key,返回这组key对应的属性,再组成一个字典

第二个方法是用来修改Model中对应Key的属性

@interface Address : NSObject
​
@property (nonatomic, copy)NSString* country;
@property (nonatomic, copy)NSString* province;
@property (nonatomic, copy)NSString* city;
@property (nonatomic, copy)NSString* district;
​
@end
  
​
int main(int argc, char * argv[]) {
    NSString * appDelegateClassName;
    @autoreleasepool {
        //模型转字典
                Address* add = [Address new];
                add.country = @"China";
                add.province = @"Guang Dong";
                add.city = @"Shen Zhen";
                add.district = @"Nan Shan";
                NSArray* arr = @[@"country",@"province",@"city",@"district"];
                NSDictionary* dict = [add dictionaryWithValuesForKeys:arr]; //把对应key所有的属性全部取出来
                NSLog(@"%@",dict);
                
                //字典转模型
                NSDictionary* modifyDict = @{@"country":@"USA",@"province":@"california",@"city":@"Los angle"};
                [add setValuesForKeysWithDictionary:modifyDict];            //用key Value来修改Model的属性
                NSLog(@"country:%@  province:%@ city:%@",add.country,add.province,add.city);
​
        appDelegateClassName = NSStringFromClass([AppDelegate class]);
    }
    return UIApplicationMain(argc, argv, nil, appDelegateClassName);
}

KVC应用

KVC这种基于运行时的编程方式具有很高的灵活性,因此在iOS开发中有着广泛的用途

动态地取值和设值

利用KVC动态的取值和设值是最基本的用途了。

用KVC来访问和修改私有变量

对于类里的私有属性,Objective-C是无法直接访问的,但是KVC是可以的。

Model和字典转换

这是KVC强大作用的又一次体现,KVC和Objc的runtime组合可以很容易的实现Model和字典的转换。

修改一些控件的内部属性

这也是iOS开发中必不可少的小技巧。众所周知很多UI控件都由很多内部UI控件组合而成的,但是Apple度没有提供这访问这些控件的API,这样我们就无法正常地访问和修改这些控件的样式。 而KVC在大多数情况可下可以解决这个问题。最常用的就是个性化UITextField中的placeHolderText了。

操作集合

Apple对KVC的valueForKey:方法作了一些特殊的实现,比如说NSArray和NSSet这样的容器类就实现了这些方法。所以可以用KVC很方便地操作集合。

用KVC实现高阶消息传递

当对容器类使用KVC时,valueForKey:将会被传递给容器中的每一个对象,而不是容器本身进行操作。结果会被添加进返回的容器中,这样,开发者可以很方便的操作集合来返回另一个集合。

实现KVO

KVO是基于KVC实现的,下面讲一下KVO的概念和实现。

标签:key,KVC,iOS,value,NSString,NSNumber,方法
From: https://blog.csdn.net/2301_80095702/article/details/142440357

相关文章

  • axios允许跨域cookie
    //添加请求拦截器service.interceptors.request.use( (config)=>{ ////在发送请求之前做些什么token //if(Session.get('token')){ // (<any>config.headers).common['Authorization']=`${Session.get('token')}`; //} //获取本......
  • 苹果iOS免越狱中控,高效管理苹果设备!
    在当前的移动设备市场,苹果的iOS系统因其出色的稳定性和安全性受到用户的青睐。然而,对于一些开发者和应用测试人员来说,如何在不越狱的情况下实现对多个iOS设备的同时群控,是一个挑战。今天,我们就来详细探讨一下在iOS免越狱环境下实现群控的方法和技巧。我们需要了解为什么iOS......
  • 苹果iOS不越狱中控系统,高效匹配app控制中心!
    苹果公司对于其生态系统的控制非常严格,旨在保护用户的隐私和数据安全,因此对第三方应用的限制较多。这种限制使得开发者在不越狱的情况下难以实现深层次的系统控制,进而影响了群控系统的发展。苹果iOS不越狱中控系统,它将为你的项目带来全新的改变!系统可以帮助你轻松实现对多个......
  • uni-app上架ios语言设置
    客户反馈了一个问题,日文的应用上架后在商店中,却显示了其他语言,解决方案如下1.添加要设置的语言2.最重要的一步,在 app-plus中添加下述代码name是app名称"app-plus":{"locales":{"ja":{"name":"xxx","a......
  • VMware ESXi 8.0U3b macOS Unlocker & OEM BIOS 2.7 标准版和厂商定制版
    VMwareESXi8.0U3bmacOSUnlocker&OEMBIOS2.7标准版和厂商定制版ESXi8.0U3标准版,Dell(戴尔)、HPE(慧与)、Lenovo(联想)、Inspur(浪潮)、Cisco(思科)、Hitachi(日立)、Fujitsu(富士通)、NEC(日电)定制版、Huawei(华为)OEM定制版请访问原文链接:https://sysin......
  • vue中axios请求数据
    首先引入包:yarnaddaxios再导入importaxiosfrom'axios'<template><div><h1>登录页面</h1><form><labelfor="username">用户名:</label><inputtype="text"id="userna......
  • vue/配置axios(前后端数据连通/api接口的调用)
    1.创建apis文件2.写入调用的api地址且暴露出去。importhttpInstancefrom'@/utils/http';exportfunctiongetHomeNav(){returnhttpInstance({url:'http://10.0.11.91:91/dailyreport/getdailyreportall',})}3.创建文件编写拦截器 代码部分//axio......
  • iOS平台RTSP|RTMP直播播放器技术接入说明
    技术背景大牛直播SDK自2015年发布RTSP、RTMP直播播放模块,迭代从未停止,SmartPlayer功能强大、性能强劲、高稳定、超低延迟、超低资源占用。无需赘述,全自研内核,行业内一致认可的跨平台RTSP、RTMP直播播放器。本文以iOS平台为例,介绍下如何集成RTSP、RTMP播放模块。技术对接 系......
  • iOS平台RTSP|RTMP直播播放器技术接入说明
    技术背景大牛直播SDK自2015年发布RTSP、RTMP直播播放模块,迭代从未停止,SmartPlayer功能强大、性能强劲、高稳定、超低延迟、超低资源占用。无需赘述,全自研内核,行业内一致认可的跨平台RTSP、RTMP直播播放器。本文以iOS平台为例,介绍下如何集成RTSP、RTMP播放模块。技术对接 系统要求S......
  • vue 配置代理 及 axios 请求封装和使用
    一.配置代理- vue.config.js const{defineConfig}=require('@vue/cli-service')module.exports=defineConfig({ transpileDependencies:true, //配置代理服务器 devServer:{  proxy:{   '/baidu':{    target:'https://ba......