「iOS」自定义Modal转场——抽屉视图的实现
「iOS」自定义Modal转场——抽屉视图的实现
文章目录
- 「iOS」自定义Modal转场——抽屉视图的实现
- 前言
- 错误尝试
- 自定义Modal转场
- 实现流程
- 自定义动画类
- UIPresentationController
- 成果展示
- 参考文章
前言
在仿写网易云的过程之中,看到学长之前仿写时实现的抽屉视图,不明觉厉,于是在仿写完3Gshared之后选择沉淀一下,来对网易云设置界面之中的抽屉视图以及圆角cell进行仿写以及学习,本来是想将这两个内容一起发为一篇博客的,但是在实现的过程之中发现,就单单让控制器从左边弹出就费了一番功夫,因此将如何实现自定义模态视图的推出,先整理为一篇笔记为先。
我是想要实现网易云那样的抽屉视图推出,即推出界面之后,右侧空白处显示的是原先控制器右侧的内容,我看到网上大部分使用transform进行平移,这样就使得空白处显示的原先视图控制器的左侧内容,于是就绕了很多弯子。
错误尝试
对于抽屉视图,我开始是想要使用UINavigationController实现(即pop和push的方法)从左到右推出和从右到左淡出的效果,即从JCThird
跳转至JCSecond
之中
//前一个视图推出控制器
-(void)pushToJCSecond {CATransition *transition = [CATransition animation];transition.duration = 0.3;transition.type = kCATransitionPush;transition.subtype = kCATransitionFromLeft; [self.navigationController.view.layer addAnimation:transition forKey:kCATransition]; JCSecond *second = [[JCSecond alloc] init];second.view.backgroundColor = [UIColor clearColor]; [self.navigationController pushViewController:second animated:YES];
}//后一个控制器的内容
(void)viewDidLoad {[super viewDidLoad];// Do any additional setup after loading the view.self.view.backgroundColor = [UIColor clearColor];UIBarButtonItem *backButton = [[UIBarButtonItem alloc] initWithTitle:@"返回" style:UIBarButtonItemStylePlain target:self action:@selector(backButtonTapped)];CGFloat width = [UIScreen mainScreen].bounds.size.width; UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, width * 5 / 6, [UIScreen mainScreen].bounds.size.height)];view.backgroundColor = [UIColor redColor];[self.view addSubview:view];self.navigationItem.leftBarButtonItem = backButton;
}
但是发现,当视图顺利的从我的设想的动画之中弹出的时候,出现了问题,我即使将控制器的背景右侧六分之一设置为透明,但是透明一侧透露的最多多只是UITabBarController的一角,情况如下,是在是解决不了这个问题,于是选择放弃。初步推出是与推出视图的负责视图即父视图有关。如有解决方法请,请看到的大佬不吝赐教。
自定义Modal转场
那既然push/pop
的方法不能做到,我就想着使用present/dismiss
模态视图的方式,能不能实现呢?我们在使用present/dismiss
的时候,一般来说能够控制present/dismiss
出来控制器的高低,能在空白处看到上一个视图的部分内容。通过学习了解,我知道了和模态视图推出相关的一个属性,是在控制器之中的modalPresentationStyle
,这个属性可以控制模态视图推出的时的形态,比如UIModalPresentationFullScreen
可以让模态视图充满整一个屏幕。但可惜的是在可选的style并不能直接实现让视图从左到右推出的功能,于是我就接着了解到了如何自定义Modal转场的转场动画。
这个过程之中需要的内容其实自我感觉称得上复杂,大致有五个内容:
1.UIViewControllerAnimatedTransitioning 一个协议,这个接口负责切换的具体内容,也即“切换中发生了什么动画”,动画实现只需要实现其两个代理方法就行
2.UIViewControllerTransitioningDelegate 一个协议,需要控制器切换的时候系统会向实现了这个接口的对象询问是否需要使用自定义的切换效果,也就是选择自定义的动画
3.UIPresentationController 控制控制器跳转的类,是 iOS8 新增的一个 API,用来控制 controller 之间的跳转特效可以用它实现自定义的弹窗,以及弹出的控制器的大小都可以根据这个来进行设置
4.modalPresentationStyle 这是UIViewController 的一个属性,就是字面意思,modal的样式,自定义的话,需要设置为Custom
5.transitioningDelegate 就是谁去实现 UIViewControllerTransitioningDelegate 这个协议的代理方法,一般用一个专门的类管理
实现流程
一开始看起来东西好像很多,我们可以慢慢来,一点一点的进行学习,首先我们要知道我们自定义一个Modal转场需要什么东西,一个遵循协议UIViewControllerAnimatedTransitioning
自定义的动画类来实现从左到右弹出的动画,以及从右到左收回的动画,我们还需要重写UIPresentationController
来控制弹出控制器的大小范围,以及添加半透明的黑色视图实现相关效果,这个可能听起来有点难理解,不过到后面就都了解了
自定义动画类
@protocol UIViewControllerAnimatedTransitioning <NSObject>// This is used for percent driven interactive transitions, as well as for
// container controllers that have companion animations that might need to
// synchronize with the main animation.
- (NSTimeInterval)transitionDuration:(nullable id <UIViewControllerContextTransitioning>)transitionContext;
// This method can only be a no-op if the transition is interactive and not a percentDriven interactive transition.
- (void)animateTransition:(id <UIViewControllerContextTransitioning>)transitionContext;@end
这是我们点进UIViewControllerAnimatedTransitioning
可以看到的内容,可以看到一共可以实现两个方法,第一个方法我们通过返回值不难看出与时间相关,进而猜测这个方法其实与动画时间相关。
我们在这两个方法之中都能够看到一个协议名字,名为UIViewControllerContextTransitioning
,这个名字含有Context
协议其实就是转场动画的核心,遵循这个协议的transitionContext
即包含了转场动画的上下文(即前一个控制器和后一个控制器)。
@protocol UIViewControllerContextTransitioning <NSObject>
//转场动画的容器
@property(nonatomic, readonly) UIView *containerView;@property(nonatomic, readonly, getter=isAnimated) BOOL animated;// The next two values can change if the animating transition is interruptible.
@property(nonatomic, readonly, getter=isInteractive) BOOL interactive; // This indicates whether the transition is currently interactive.
@property(nonatomic, readonly) BOOL transitionWasCancelled;@property(nonatomic, readonly) UIModalPresentationStyle presentationStyle;- (void)completeTransition:(BOOL)didComplete;//通过两个to和from的枚举量,能在上下文之中获得相应的控制器
- (nullable __kindof UIViewController *)viewControllerForKey:(UITransitionContextViewControllerKey)key;//获取上下文视图大小
- (CGRect)initialFrameForViewController:(UIViewController *)vc;
- (CGRect)finalFrameForViewController:(UIViewController *)vc;
@end
了解了这些我们就可以先写一个,一个自定义的动画类了,首先这个类的父类是NSOject,且需要遵循 UIViewControllerAnimatedTransitioning
协议,头文件如下:
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN@interface slide : NSObject <UIViewControllerAnimatedTransitioning>@property (nonatomic, assign) BOOL isPresentation;@endNS_ASSUME_NONNULL_END
有细心的读者就会发现了,这个头文件之中还定义了布尔的属性,这个属性有什么用呢,前面我们说过,这个协议就只有两种方法,一个关于动画时间,一个关于模态视图的上下文以及动画,由于没有对present/dismiss
进行明确的划分,所以我们要在属性之中添加一个属性来判断是对视图进行present/dismiss
。
接下来就是.m文件 —— 事先声明JCSecond以及JCThird为两个控制器的名称
#import "slide.h"@implementation slide- (NSTimeInterval)transitionDuration:(id<UIViewControllerContextTransitioning>)transitionContext {return 0.3;
}- (void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext {UIView *containerView = [transitionContext containerView];//to是指变化的下文,from是指变化的上文UIViewController *toViewController = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];UIViewController *fromViewController = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];UIView *toView = toViewController.view;UIView *fromView = fromViewController.view;//用于获取源视图控制器(fromViewController)在转场开始前的位置信息。CGRect initialFrame = [transitionContext initialFrameForViewController:fromViewController];//用于获取目标视图控制器(toViewController)在转场结束后的位置信息。CGRect finalFrame = [transitionContext finalFrameForViewController:toViewController];//如果决定是将视图present则将toView加入containerView之中,并将 toView.frame先置于视图最后位置的左边,这样当动画变化的时候就会实现从左到右滑滑出if (self.isPresentation) {toView.frame = CGRectOffset(finalFrame, -finalFrame.size.width, 0);[containerView addSubview:toView];}UIView *animatingView = self.isPresentation ? toView : fromView;//确保拿到的都是JCSecond这个控制器以便进行动画//如果为dismiss那么就将最后的位置置于JCSecond的左边CGRect targetFrame = self.isPresentation ? finalFrame : CGRectOffset(initialFrame, -initialFrame.size.width, 0);[UIView animateWithDuration:[self transitionDuration:transitionContext] animations:^{animatingView.frame = targetFrame;} completion:^(BOOL finished) {if (!self.isPresentation) {[fromView removeFromSuperview];//如果为dismiss就将JCSecond全部移除}[transitionContext completeTransition:YES];}];
}@end
在这个.m文件的第二个方法之中,我们看到了很多,之前我们在UIViewControllerContextTransitioning
之中看到的东西,首先是获得上下文的控制器,但是注意一点在present
和dismiss
的上下文并不相同,也就是说在present
之中,toView是指JCSecond
,fromVIew是指JCThird
,在dismiss
之中toVIew指的是JCSecond
,fromView指的是JCThird
。
实现了自定义类之中我们就要,控制器之中的JCThird
,去告诉编译器我们自己实现了一个动画,并将其运用至了present/dismiss
的模态视图变化之中,我们就要先让该视图控制器实现协议UIViewControllerTransitioningDelegate
之中的方法了,这个协议之中的方法就是告诉编译器我们想要使用何种动画方式进行’push/dismiss’。引入我们刚刚写的自定义动画类slide
,告诉编译器需要用slide
这个动画实例进行变化,以下就是JCThird
的代码
- (void)pushToJCSecond {JCSecond *second = [[JCSecond alloc] init];second.view.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:@"back3.jpeg"]];//记得将modal改为自定义second.modalPresentationStyle = UIModalPresentationCustom;//实现协议的代理对象second.transitioningDelegate = self;[self presentViewController:second animated:YES completion:nil];
}
//管理present动画的
- (id<UIViewControllerAnimatedTransitioning>)animationControllerForPresentedController:(UIViewController *)presented presentingController:(UIViewController *)presenting sourceController:(UIViewController *)source {slide *animationController = [[slide alloc] init];animationController.isPresentation = YES;return animationController;
}
//管理dismiss动画的
- (id<UIViewControllerAnimatedTransitioning>)animationControllerForDismissedController:(UIViewController *)dismissed {slide *animationController = [[slide alloc] init];animationController.isPresentation = NO;return animationController;
}
我们运行一下试试看:
不难发现,有点像了是不是,但是好像还是缺了什么,就是右边空白视图需要从亮到灰,而不是和弹出来的抽屉视图的亮度相同,笔者先前试过在viewWillDisappear
之中加入一个半透明的灰色视图,结果发现由于覆盖的半透明视图是覆盖在JCThird之中,本身的UITabBarController
并不会发生覆盖,而且present
出来的视图控制器,界面仍然占据整个屏幕,这对于后面添加手势去dismiss视图也是一个难度。于是根据相关知识,我发现UIPresentationController
似乎能够实现我想要完成的效果。
JCSecond占据了整个屏幕
UIPresentationController
当我们使用presnt方法的时候控制器的presentationController
就会提前创建好了,它负责管理视图控制器之间的呈现(presentation)和解散(dismissal)过程。
-
presentationTransitionWillBegin
:- 作用:在呈现过渡即将开始时调用。
- 用法:在此方法中执行呈现过渡的准备工作,如设置背景视图、添加自定义动画等。
-
presentationTransitionDidEnd:
:- 作用:在呈现过渡结束时调用。
- 用法:在此方法中执行呈现过渡完成后的清理工作,如处理用户交互、设置最终状态等。
-
dismissalTransitionWillBegin
:- 作用:在解散过渡即将开始时调用。
- 用法:在此方法中执行解散过渡的准备工作,如添加解散动画效果、隐藏视图等。
-
dismissalTransitionDidEnd:
:- 作用:在解散过渡结束时调用。
- 用法:在此方法中执行解散过渡完成后的清理工作,如移除视图、恢复状态等。
-
frameOfPresentedViewInContainerView
:- 作用:返回呈现视图在容器视图中的位置和大小。
- 用法:用于指定呈现视图在容器视图中的布局,可以自定义呈现视图的位置和大小。
我们可以根据重写视图控制器之中这些类似的方法一样,自己自定义 UIPresentationController
的行为已实现自己的需求。
OK了解完了原理,那我们就开始重写方法吧
#import <UIKit/UIKit.h>NS_ASSUME_NONNULL_BEGIN@interface present : UIPresentationController@endNS_ASSUME_NONNULL_END
——————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
#import "present.h"@implementation present
- (CGRect)frameOfPresentedViewInContainerView {CGFloat width = self.containerView.bounds.size.width * 5 / 6;return CGRectMake(0, 0, width, self.containerView.bounds.size.height);
}- (void)presentationTransitionWillBegin {UIView *dimmingView = [[UIView alloc] initWithFrame:self.containerView.bounds];dimmingView.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.5];dimmingView.alpha = 0.0;dimmingView.tag = 1001;[self.containerView addSubview:dimmingView];[UIView animateWithDuration:0.3 animations:^{dimmingView.alpha = 1.0;}];UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tap:)];[dimmingView addGestureRecognizer:tapGesture];
}- (void)tap:(UITapGestureRecognizer *)gesture {[self.presentingViewController dismissViewControllerAnimated:YES completion:nil];
}- (void)dismissalTransitionWillBegin {UIView *dimmingView = [self.containerView viewWithTag:1001];[UIView animateWithDuration:0.3 animations:^{dimmingView.alpha = 0.0;} completion:^(BOOL finished) {[dimmingView removeFromSuperview];}];
}
@end
我重写了frameOfPresentedViewInContainerView
presentationTransitionWillBegin
以及 dismissalTransitionWillBegin
这三个方法,其中frameOfPresentedViewInContainerView
就是限制了JCSecond
的范围宽度为六分之五。
presentationTransitionWillBegin
是在视图被present之前添加了一个黑色半透明的背景颜色,而在视图被present到屏幕上的时候,做一个动画渐变将半透明的黑色背景颜色逐渐显示(即alpha从0到1的过程),然后就是手势的添加,我们将其添加至背景视图的dimmingView
,由于我们前面frameOfPresentedViewInContainerView
设定了JCSecond
的具体大小,所以dimmingView
会被JCSecond
覆盖,所以只有我们点击到灰色的背景部分,这个抽屉视图才会执行手势的内容
dismissalTransitionWillBegin
其实内容大同小异,只是将背景视图通过动画取消了而已,然后在动画结束的时候将背景视图移除,没有其他的内容。
成果展示
完整内容如下:
好了我们这样终于完成了我们想要的抽屉视图,没想到一个看似简单的内容,自己学习以及整理笔记整理了快有两天之多,果然还是学习的内容太少了,没想到实现这个简单的内容还需要了解这么多东西,果然学习之路还是茫茫啊😭
参考文章
自定义Modal转场-模仿push & pop
iOS 自定义转场动画浅谈
你真的了解iOS中控制器的present和dismiss吗?
UIViewControllerAnimatedTransitioning
相关文章:

「iOS」自定义Modal转场——抽屉视图的实现
「iOS」自定义Modal转场——抽屉视图的实现 文章目录 「iOS」自定义Modal转场——抽屉视图的实现前言错误尝试自定义Modal转场实现流程自定义动画类UIPresentationController 成果展示参考文章 前言 在仿写网易云的过程之中,看到学长之前仿写时实现的抽屉视图&…...

【数据结构】顺序结构实现:特殊完全二叉树(堆)+堆排序
二叉树 一.二叉树的顺序结构二.堆的概念及结构三.堆的实现1.堆的结构2.堆的初始化、销毁、打印、判空3.堆中的值交换4.堆顶元素5.堆向上调整算法:实现小堆的插入6.堆向下调整算法:实现小堆的删除7.堆的创建1.堆向上调整算法:建堆建堆的时间复…...
【c++学习技术栈】
c学习技术栈 基础c基础组件中间件框架devops性能目标岗位 基础 计算机网络数据结构与算法操作系统linux c 基础组件 池式组件:线程池,内存池,db数据库连接池原子,无锁队列,ringbuffer,定时器。日志&…...

swift 自定义DatePacker
import Foundationenum AppDatePickerStyle {case KDatePickerDate //年月日case KDatePickerTime //年月日时分case kDatePickerMonth // 年月case KDatePickerSecond //秒}class AppDatePicker: UIView {private let jk_rootView UIApplication.shared.keyWindow!pri…...

MySQL事务,锁,MVCC总结
mysql中最重要的就是事务,其四大特性让我们维持了数据的平衡,一致。那么事务究竟是什么,与什么相关,他的使用步骤,以及使用过程中我们会遇到什么问题呢?下面我们一起学习交流! 1.MySQL的存储引擎ÿ…...

24/8/7 算法笔记 支持向量机回归问题天猫双十一
import numpy as np from sklearn.svm import SVR import matplotlib.pyplot as plt X np.linspace(0,2*np.pi,50).reshape(-1,1) y np.sin(X) plt.scatter(X,y) 建模 线性核函数 svr SVR(kernel linear) svr.fit(X,y.ravel())#变成一维y_ svr.predict(X) plt.scatter(…...

win7系统利用定时启动+脚本实现MySQL文件自动备份
前言 最近接到项目,数据量不大但对运行数据的安全性要求极高,为避免因不可抗拒因素导致的数据丢失,选择机械硬盘作为数据存储盘,并使用脚本方式对文件进行备份 一、脚本 下面为自动备份文件的 脚本,可根据自身情况进…...

基于Java多线程处理数据
基于Java多线程处理数据 背景代码实现 背景 在日常工作中,有一个同步企微客户-学员关系接口的定时任务在执行中随着数据量的不断增长,定时任务的执行结束时间也出现了当天执行不完的情况,影响到了正常业务的运行。基于这种情况,在…...
日常知识点之遇到问题结构体按位构造协议时和期望不一致,研究记录一下
遇到一个问题,在做业务的时候,涉及到协议相关,按位进行设计,用结构体来模拟协议时,发现内存存储和实际目的不一致,知道是大小端以及计算机底层存储逻辑相关,所以研究了一下。 1:简单…...
spring mvc 文件下载
在web中下载的方式大多基于servlet,在web.xml中配置下载路径,这里再介绍json(转成base64字符串)和blob的使用方式 servlet WEB-INF/web.xml <!--url映射--> <servlet-mapping><servlet-name>DowloadServlet</servlet-name>&l…...

Qt WebEngine基于WebEngineScript注入js脚本
在之前的文章中,我们介绍了Qt WebEngine注入js的用法,及runJavaScript()的用法,该方法主要是用在页面加载完成后,为了和网页做一些交互时使用。有时候需要监听网页加载完成的一些状态或信息,则需要网页加载前注入js来实…...

案例分享-国外UI设计界面赏析
国外UI设计倾向于简洁的布局和清晰的排版,减少视觉干扰,提升用户体验。通过合理的色彩搭配和图标设计,营造舒适愉悦的使用氛围。 设计师不拘泥于传统框架,勇于尝试新元素和理念,使界面独特有趣。同时,强调以…...

用PyTorch 从零开始构建 BitNet 1.58bit
我们手动实现BitNet的编写,并进行的一系列小实验证实,看看1.58bit 模型是否与全精度的大型语言模型相媲美! 什么是量化以及为什么需要它? 量化是用更少的比特数表示浮点数的过程。当两个数字使用不同的比特数进行量化时…...

信创安全 | 新一代内网安全方案—零信任沙盒
在当今数字化时代,访问安全和数据安全成为企业面临的重要挑战。传统的边界防御已经无法满足日益复杂的内网办公环境,层出不穷的攻击手段已经让市场单一的防御手段黔驴技穷。当企业面临越来越复杂的网络威胁和数据泄密风险时,更需要一种综合的…...
Redis的回收策略(淘汰策略)
volatile-lru :从已设置过期时间的数据集( server.db[i].expires )中挑选最近最少使用的数据淘汰 volatile-ttl : 从已设置过期时间的数据集( server.db[i].expires ) 中挑选将要过期的数据淘汰 volatile…...

Electron-builder 打包
项目比较简单,仅使用了 Electron 原生js 安装 electron-builder npm install electron-builder --dev配置 package.json 中的打包命令 {"script":{// ..."dev": "electron .","pack": "electron-builder"} }添…...

笔试练习day3
目录 BC149 简写单词题目解析代码 dd爱框框题目解析解析代码方法一暴力解法方法二同向双指针(滑动窗口) 除2!题目解析解法模拟贪心堆 感谢各位大佬对我的支持,如果我的文章对你有用,欢迎点击以下链接 🐒🐒🐒 个人主页 🥸…...
企业想要将大模型技术应用到企业管理中需具备什么条件?
#企业 #企业管理 #大模型 企业想要将大模型技术应用到企业管理中,需要考虑以下几个关键条件: 1.明确的需求定位:企业应首先诊断自身的业务场景、数据、算法、基础设施预算以及战略等能力,明确大模型能够为企业带来的具体赋…...

go 事件机制(观察者设计模式)
背景: 公司目前有个业务,收到数据后,要分发给所有的客户端或者是业务模块,类似消息通知这样的需求,自然而然就想到了事件,观察者比较简单就自己实现以下,确保最小功能使用支持即可,其…...

RISC-V竞赛|第二届 RISC-V 软件移植及优化锦标赛报名正式开始!
目录 赛事背景 赛道方向 适配夺旗赛 优化竞速赛 比赛赛题(总奖金池8万元!) 🔥竞速赛 - OceanBase 移植与优化 比赛赛程(暂定) 赛事说明 「赛事背景」 为了推动 RISC-V 软件生态更快地发展࿰…...
HTML 语义化
目录 HTML 语义化HTML5 新特性HTML 语义化的好处语义化标签的使用场景最佳实践 HTML 语义化 HTML5 新特性 标准答案: 语义化标签: <header>:页头<nav>:导航<main>:主要内容<article>&#x…...

iOS 26 携众系统重磅更新,但“苹果智能”仍与国行无缘
美国西海岸的夏天,再次被苹果点燃。一年一度的全球开发者大会 WWDC25 如期而至,这不仅是开发者的盛宴,更是全球数亿苹果用户翘首以盼的科技春晚。今年,苹果依旧为我们带来了全家桶式的系统更新,包括 iOS 26、iPadOS 26…...
CVPR 2025 MIMO: 支持视觉指代和像素grounding 的医学视觉语言模型
CVPR 2025 | MIMO:支持视觉指代和像素对齐的医学视觉语言模型 论文信息 标题:MIMO: A medical vision language model with visual referring multimodal input and pixel grounding multimodal output作者:Yanyuan Chen, Dexuan Xu, Yu Hu…...
PHP和Node.js哪个更爽?
先说结论,rust完胜。 php:laravel,swoole,webman,最开始在苏宁的时候写了几年php,当时觉得php真的是世界上最好的语言,因为当初活在舒适圈里,不愿意跳出来,就好比当初活在…...
服务器硬防的应用场景都有哪些?
服务器硬防是指一种通过硬件设备层面的安全措施来防御服务器系统受到网络攻击的方式,避免服务器受到各种恶意攻击和网络威胁,那么,服务器硬防通常都会应用在哪些场景当中呢? 硬防服务器中一般会配备入侵检测系统和预防系统&#x…...
在 Nginx Stream 层“改写”MQTT ngx_stream_mqtt_filter_module
1、为什么要修改 CONNECT 报文? 多租户隔离:自动为接入设备追加租户前缀,后端按 ClientID 拆分队列。零代码鉴权:将入站用户名替换为 OAuth Access-Token,后端 Broker 统一校验。灰度发布:根据 IP/地理位写…...

Vue2 第一节_Vue2上手_插值表达式{{}}_访问数据和修改数据_Vue开发者工具
文章目录 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染2. 插值表达式{{}}3. 访问数据和修改数据4. vue响应式5. Vue开发者工具--方便调试 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染 准备容器引包创建Vue实例 new Vue()指定配置项 ->渲染数据 准备一个容器,例如: …...

SpringBoot+uniapp 的 Champion 俱乐部微信小程序设计与实现,论文初版实现
摘要 本论文旨在设计并实现基于 SpringBoot 和 uniapp 的 Champion 俱乐部微信小程序,以满足俱乐部线上活动推广、会员管理、社交互动等需求。通过 SpringBoot 搭建后端服务,提供稳定高效的数据处理与业务逻辑支持;利用 uniapp 实现跨平台前…...

AI,如何重构理解、匹配与决策?
AI 时代,我们如何理解消费? 作者|王彬 封面|Unplash 人们通过信息理解世界。 曾几何时,PC 与移动互联网重塑了人们的购物路径:信息变得唾手可得,商品决策变得高度依赖内容。 但 AI 时代的来…...
#Uniapp篇:chrome调试unapp适配
chrome调试设备----使用Android模拟机开发调试移动端页面 Chrome://inspect/#devices MuMu模拟器Edge浏览器:Android原生APP嵌入的H5页面元素定位 chrome://inspect/#devices uniapp单位适配 根路径下 postcss.config.js 需要装这些插件 “postcss”: “^8.5.…...