教你在不使用框架的情况下也能写出现代化 PHP 代码

教你在不使用框架的情况下也能写出现代化 php 代码

我为你们准备了一个富有挑战性的事情。接下来你们将以 框架的方式开启一个项目之旅。

首先声明, 这篇并非又臭又长的反框架裹脚布文章。也不是推销 非原创 思想 。毕竟, 我们还将在接下来的开发之旅中使用其他框架开发者编写的辅助包。我对这个领域的创新也是持无可非议的态度。

这无关他人,而是关乎己身。作为一名开发者,它将有机会让你成长。

也许无框架开发令你受益匪浅的地方就是,可以从底层运作的层面中汲取丰富的知识。抛却依赖神奇的,帮你处理无法调试和无法真正理解的东西的框架,你将清楚的看到这一切是如何发生的。

立即学习“PHP免费学习笔记(深入)”;

很有可能下一份工作中,你并不能随心所以地选择框架开拓新项目。现实就是,在很多高价值,关键业务的 PHP 工作中均使用现有应用。 并且该应用程序是否构建在当前令人舒爽的 Laravel 或 Symfony 等流行框架中,亦或是陈旧过时的 CodeIgniter 或者 FuelPHP 中,更有甚者它可能广泛出现在令人沮丧的 “面向包含体系结构” 的传统的 PHP 应用 之中,所以框架开发会在将来你所面临的任何 PHP 项目中助你一臂之力。

上古时代, 因为 某些系统 不得不解释分发 HTTP 请求,发送 HTTP 响应,管理依赖关系,无框架开发就是痛苦的鏖战。缺乏行业标准必然意味着,框架中的这些组件高度耦合 。如果你从无框架开始,你终将难逃自建框架的命运。

时至今日,幸亏有 PHP-FIG 完成所有的自动加载和交互工作,无框架开发并非让你白手起家。各色供应商都有这么多优秀的可交互的软件包。把他们组合起来容易得超乎你的想象!

PHP 是如何工作的?

在做其他事之前,搞清楚 PHP 如何与外界沟通是非常重要的。

PHP 以请求 / 响应为周期运行服务端应用程序。与你的应用程序的每一次交互——无论是来自浏览器,命令行还是 REST API ——都是作为请求进入应用程序的。 当接收到请求以后:

程序开始启动;

开始处理请求;

产生响应;

接着,响应返回给产生请求的相应客户端;

最后程序关闭。

每一个 请求都在重复以上的交互。

前端控制器

用这些知识把自己武装起来以后,就可以先从我们的前端控制器开始编写程序了。前端控制器是一个 PHP 文件,它处理程序的每一个请求。控制器是请求进入程序后遇到的第一个 PHP 文件,并且(本质上)也是响应走出你应用程序所经过的最后一个文件。

我们使用经典的 Hello, world! 作为例子来确保所有东西都正确连接上,这个例子由 PHP 的内置服务器  驱动。在你开始这样做之前,请确保你已经安装了 PHP7.1 或者更高版本。

创建一个含有 public 目录的项目,然后在该目录里面创建一个index.php 文件,文件里面写入如下代码:

<?phpdeclare(strict_types=1);echo 'Hello, world!';

注意,这里我们声明了使用严格模式 —— 作为最佳实践,你应该在应用程序的 每个 PHP 文件的开头 都这样做。因为对从你后面来的开发者来说类型提示对 调试和清晰的交流意图很重要 。

使用命令行(比如 macOS 的终端)切换到你的项目目录并启动 PHP 的内置服务器。

php -S localhost:8080 -t public/

现在,在浏览器中打开 http://localhost:8080/ 。是不是成功地看到了 “Hello, world!” 输出?

很好。接下来我们可以开始进入正题了!

自动加载与第三方包

当你第一次使用 PHP 时,你可能会在你的程序中使用 includes 或 requires 语句来从其他 PHP 文件导入功能和配置。 通常,我们会避免这么干,因为这会使得其他人更难以遵循你的代码路径和理解依赖在哪里。这让调试成为了一个 真正的 噩梦。

解决办法是使用自动加载(autoloading)。 自动加载的意思是:当你的程序需要使用一个类, PHP 在调用该类的时候知道去哪里找到并加载它。虽然从 PHP 5 开始就可以使用这个特性了, 但是得益于 PSR-0 ( 自动加载标准,后来被 PSR-4 取代),其使用率才开始有真正的提升。

我们可以编写自己的自动加载器来完成任务,但是由于我们将要使用的管理第三方依赖的  Composer 已经包含了一个完美的可用的自动加载器,那我们用它就行了。

确保你已经在你的系统上 安装 了 Composer。然后为此项目初始化 Composer:

composer init

这条命令通过交互式引导你创建 composer.json 配置文件。 一旦文件创建好了,我们就可以在编辑器中打开它然后向里面写入 autoload 字段,使他看起来像这个样子(这确保了自动加载器知道从哪里找到我们项目中的类):

{    "name": "kevinsmith/no-framework",    "description": "An example of a modern PHP application bootstrapped without a framework.",    "type": "project",    "require": {},    "autoload": {        "psr-4": {            "ExampleApp": "class="lazy" data-src/"        }    }}

现在为此项目安装 composer,它引入了依赖(如果有的话),并为我们创建好了自动加载器:

composer install

更新 public/index.php 文件来引入自动加载器。在理想情况下,这将是你在程序当中使用的少数『包含』语句之一。

<?phpdeclare(strict_types=1);require_once dirname(__DIR__) . '/vendor/autoload.php';echo 'Hello, world!';

此时如果你刷新浏览器,你将不会看到任何变化。因为自动加载器没有修改或者输出任何数据,所以我们看到的是同样的内容。让我们把 Hello, world! 这个例子移动到一个已经自动加载的类里面看看它是如何运作的。

在项目根目录创建一个名为 class=”lazy” data-src 的目录,然后在里面添加一个叫 HelloWorld.php 的文件,写入如下代码:

<?phpdeclare(strict_types=1);namespace ExampleApp;class HelloWorld{    public function announce(): void    {        echo 'Hello, autoloaded world!';    }}

现在到 public/index.php 里面用  HelloWorld 类的 announce 方法替换掉 echo 语句。

// ...require_once dirname(__DIR__) . '/vendor/autoload.php';$helloWorld = new ExampleAppHelloWorld();$helloWorld->announce();

刷新浏览器查看新的信息!

什么是依赖注入?

依赖注入是一种编程技术,每个依赖项都供给它需要的对象,而不是在对象外获得所需的信息或功能。

举个例子,假设应用中的类方法需要从数据库中读取。为此,你需要一个数据库连接。常用的技术就是创建一个全局可见的新连接。

class AwesomeClass{    public function doSomethingAwesome()    {        $dbConnection = return new PDO(            "{$_ENV['type']}:host={$_ENV['host']};dbname={$_ENV['name']}",            $_ENV['user'],            $_ENV['pass']        );        // Make magic happen with $dbConnection    }}

但是这样做显得很乱,它把一个并非属于这里的职责置于此地—创建一个 数据库连接对象 检查凭证 还有 处理一些连接失败的问题—它会导致应用中出现 大量  重复代码。如果你尝试对这个类进行单元测试,会发现根本不可行。这个类和应用环境以及数据库高度耦合。

相反,为何不一开始就搞清楚你的类需要什么?我们只需要首先将 “PDO” 对象注入该类即可。

class AwesomeClass{    private $dbConnection;    public function __construct(PDO $dbConnection)    {        $this->dbConnection = $dbConnection;    }    public function doSomethingAwesome()    {        // Make magic happen with $this->dbConnection    }}

这样更简洁清晰易懂,且更不易产生 Bug。通过类型提示和依赖注入,该方法可以清楚准确地声明它要做的事情,而无需依赖外部调用去获取。在做单元测试的时候,我们可以很好地模拟数据库连接,并将其传入使用。

依赖注入容器 是一个工具,你可以围绕整个应用程序来处理创建和注入这些依赖关系。容器并不需要能够使用依赖注入技术,但随着应用程序的增长并变得更加复杂,它将大有裨益。

我们将使用 PHP 中最受欢迎的 DI 容器之一:名副其实的 PHP-DI。(值得推荐的是它文档中的  依赖注入另解 可能会对读者有所帮助)

依赖注入容器

现在我们已经安装了 Composer ,那么安装 PHP-DI 就轻而易举了,我们继续回到命令行来搞定它。

composer require php-di/php-di

修改 public/index.php 用来配置和构建容器。

// ...require_once dirname(__DIR__) . '/vendor/autoload.php';$containerBuilder = new DIContainerBuilder();$containerBuilder->useAutowiring(false);$containerBuilder->useAnnotations(false);$containerBuilder->addDefinitions([    ExampleAppHelloWorld::class => DIcreate(ExampleAppHelloWorld::class)]);$container = $containerBuilder->build();$helloWorld = $container->get(ExampleAppHelloWorld::class);$helloWorld->announce();

没啥大不了的。它仍是一个单文件的简单示例,你很容易能看清它是怎么运行的。

迄今为止, 我们只是在 配置容器 ,所以我们必须 显式地声明依赖关系 (而不是使用 自动装配 或 注解),并且从容器中检索 HelloWorld 对象。

小贴士:自动装配在你开始构建应用程序的时候是一个很不错的特性,但是它隐藏了依赖关系,难以维护。 很有可能在接下里的岁月里, 另一个开发者在不知情的状况下引入了一个新库,然后就造就了多个库实现一个单接口的局面,这将会破坏自动装配,导致一系列让接手者很容易忽视的的不可见的问题。

尽量 porting.php”>引入命名空间,可以增加代码的可读性。

useAutowiring(false);$containerBuilder->useAnnotations(false);$containerBuilder->addDefinitions([    HelloWorld::class => create(HelloWorld::class)]);$container = $containerBuilder->build();$helloWorld = $container->get(HelloWorld::class);$helloWorld->announce();

现在看来,我们好像是把以前已经做过的事情再拿出来小题大做。

毋需烦心,当我们添加其他工具来帮助我们引导请求时,容器就有用武之地了。它会在适当的时机下按需加载正确的类。

中间件

如果把你的应用想象成一个洋葱,请求从外部进入,到达洋葱中心,最后变成响应返回出去。那么中间件就是洋葱的每一层。它接收请求并且可以处理请求。要么把请求传递到更里层,要么向更外层返回一个响应(如果中间件正在检查请求不满足的特定条件,比如请求一个不存在的路由,则可能发生这种情况)。

如果请求通过了所有的层,那么程序就会开始处理它并把它转换为响应,中间件接收到响应的顺序与接收到请求的顺序相反,并且也能对响应做修改,然后再把它传递给下一个中间件。

下面是一些中间件用例的闪光点:

在开发环境中调试问题

在生产环境中优雅的处理异常

对传入的请求进行频率限制

对请求传入的不支持资源类型做出响应

处理跨域资源共享(CORS)

将请求路由到正确的处理类

那么中间件是实现这些功能的唯一方式吗?当然不是。但是中间件的实现使得你对请求 / 响应这个生命周期的理解更清晰。这也意味着你调试起来更简单,开发起来更快速。

我们将从上面列出的最后一条用例,也就是路由,当中获益。

路由

路由依靠传入的请求信息来确定应当由哪个类来处理它。(例如 URI  /products/purple-dress/medium 应该被  ProductDetails::class类接收处理,同时 purple-dress 和 medium 作为参数传入)

在范例应用中,我们将使用流行的 FastRoute 路由,基于 PSR-15兼容的中间件实现。

中间件调度器

为了让我们的应用可以和 FastRoute 中间件—以及我们安装的其他中间件协同工作—我们需要一个中间件调度器。

PSR-15是为中间件和调度器定义接口的中间件标准(在规范中又称“请求处理器”),它允许各式各样的中间件和调度器互相交互。我们只需选择兼容 PSR-15 的调度器,这样就可以确保它能和任何兼容 PSR-15 的中间件协同工作。

我们先安装一个 Relay 作为调度器。

composer require relay/relay:2.x@dev

而且根据 PSR-15 的中间件标准要求实现可传递 兼容 PSR-7 的 HTTP 消息, 我们使用 ramework.github.io/zend-diactoros/”>Zend Diactoros 作为 PSR-7 的实现。

composer require zendframework/zend-diactoros

我们用 Relay 去接收中间件。

// ...use DIContainerBuilder;use ExampleAppHelloWorld;use RelayRelay;use ZendDiactorosServerRequestFactory;use function DIcreate;// ...$container = $containerBuilder->build();$middlewareQueue = [];$requestHandler = new Relay($middlewareQueue);$requestHandler->handle(ServerRequestFactory::fromGlobals());

我们在第 16 行使用 ServerRequestFactory::fromGlobals() 把 ramework.github.io/zend-diactoros/usage/#marshaling-an-incoming-request”>创建新请求的必要信息合并起来 然后把它传给 Relay。这正是 Request 进入我们中间件堆栈的起点。

现在我们继续添加 FastRoute 和请求处理器中间件。(FastRoute 确定请求是否合法,究竟能否被应用程序处理,然后请求处理器发送 Request 到路由配置表中已注册过的相应处理程序中)

composer require middlewares/fast-route middlewares/request-handler

然后我们给 Hello, world! 处理类定义一个路由。我们在此使用 /hello 路由来展示基本 URI 之外的路由。

// ...use DIContainerBuilder;use ExampleAppHelloWorld;use FastRouteRouteCollector;use MiddlewaresFastRoute;use MiddlewaresRequestHandler;use RelayRelay;use ZendDiactorosServerRequestFactory;use function DIcreate;use function FastRoutesimpleDispatcher;// ...$container = $containerBuilder->build();$routes = simpleDispatcher(function (RouteCollector $r) {    $r->get('/hello', HelloWorld::class);});$middlewareQueue[] = new FastRoute($routes);$middlewareQueue[] = new RequestHandler();$requestHandler = new Relay($middlewareQueue);$requestHandler->handle(ServerRequestFactory::fromGlobals());

为了能运行,你还需要修改 HelloWorld 使其成为一个可调用的类, 也就是说 这里类可以像函数一样被随意调用。

// ...class HelloWorld{    public function __invoke(): void    {        echo 'Hello, autoloaded world!';        exit;    }}

(注意在魔术方法 __invoke() 中加入exit;。 我们只需1秒钟就能搞定——只是不想让你遗漏这个事)

现在打开 http://localhost:8080/hello ,开香槟吧!

万能胶水

睿智的读者可能很快看出,虽然我们仍旧囿于配置和构建 DI 容器的藩篱之中,容器现在实际上对我们毫无用处。调度器和中间件在没有它的情况下也一样运作。

那它何时才能发挥威力?

嗯,如果—在实际应用程序中总是如此——HelloWorld类具有依赖关系呢?

我们来讲解一个简单的依赖关系,看看究竟发生了什么。

// ...class HelloWorld{    private $foo;    public function __construct(string $foo)    {        $this->foo = $foo;    }    public function __invoke(): void    {        echo "Hello, {$this->foo} world!";        exit;    }}

刷新浏览器..

WOW!

看下这个 ArgumentCountError.

发生这种情况是因为 HelloWorld 类在构造的时候需要注入一个字符串才能运行,在此之前它只能等着。 正是容器要帮你解决的痛点。
我们在容器中定义该依赖关系,然后将容器传给 RequestHandler 去 解决这个问题。

// ...use ZendDiactorosServerRequestFactory;use function DIcreate;use function DIget;use function FastRoutesimpleDispatcher;// ...$containerBuilder->addDefinitions([    HelloWorld::class => create(HelloWorld::class)        ->constructor(get('Foo')),    'Foo' => 'bar']);$container = $containerBuilder->build();// ...$middlewareQueue[] = new FastRoute($routes);$middlewareQueue[] = new RequestHandler($container);$requestHandler = new Relay($middlewareQueue);$requestHandler->handle(ServerRequestFactory::fromGlobals());

嗟夫!当刷新浏览器的时候, “Hello, bar world!”将映入你的眼帘!

正确地发送响应

是否还记得我之前提到过的位于 HelloWorld 类中的 exit 语句?

当我们构建代码时,它可以让我们简单粗暴的获得响应,但是它绝非输出到浏览器的最佳选择。这种粗暴的做法给 HelloWorld 附加了额外的响应工作——其实应该由其他类负责的——它会过于复杂的发送所有的头部信息和 状态码,然后立刻退出了应用,使得 HelloWorld 之后 的中间件也无机会运行了。

记住,每个中间件都有机会在 Request 进入我们应用时修改它,然后 (以相反的顺序) 在响应输出时修改响应。 除了 Request 的通用接口, PSR-7 同样也定义了另外一种 HTTP 消息结构,以辅助我们在应用运行周期的后半部分之用:Response。(如果你想真正了解这些细节,请阅读 HTTP 消息以及为何 PSR-7 请求和响应标准这么碉堡。)

修改 HelloWorld 返回一个 Response。

// ...namespace ExampleApp;use PsrHttpMessageResponseInterface;class HelloWorld{    private $foo;    private $response;    public function __construct(        string $foo,        ResponseInterface $response    ) {        $this->foo = $foo;        $this->response = $response;    }    public function __invoke(): ResponseInterface    {        $response = $this->response->withHeader('Content-Type', 'text/html');        $response->getBody()            ->write("Hello, {$this->foo} world!");        return $response;    }}

然后修改容器给 HelloWorld 提供一个新的 Response 对象。

// ...use MiddlewaresRequestHandler;use RelayRelay;use ZendDiactorosResponse;use ZendDiactorosServerRequestFactory;use function DIcreate;// ...$containerBuilder->addDefinitions([    HelloWorld::class => create(HelloWorld::class)        ->constructor(get('Foo'), get('Response')),    'Foo' => 'bar',    'Response' => function() {        return new Response();    },]);$container = $containerBuilder->build();// ...

如果你现在刷新页面,会发现一片空白。我们的应用正在从中间件调度器返回正确的 Response 对象,但是… 肿么回事?

它根本啥都没干,就这么回事。

我们还需要一件东西来包装下:发射器。发射器位于应用程序和 Web 服务器(Apache,nginx等)之间,将响应发送给发起请求的客户端。它实际上拿到了 Response 对象并将其转化为 服务端 API 可理解的信息。

喜大普奔! 我们已经用来封装请求的 Zend Diactoros 包同样也内置了发送 PSR-7 响应的发射器。

值得注意的是,为了举例,我们只是对发射器的使用小试牛刀。虽然它们可能会更复杂点,真正的应用应该配置成自动化的流式发射器用来应对大量下载的情况, ramework.zend.com/blog/2017-09-14-diactoros-emitters.html”>Zend 博客展示了如何实现它。

修改 public/index.php ,用来从调度器那里接收 Response ,然后传给发射器。

// ...use RelayRelay;use ZendDiactorosResponse;use ZendDiactorosResponseSapiEmitter;use ZendDiactorosServerRequestFactory;use function DIcreate;// ...$requestHandler = new Relay($middlewareQueue);$response = $requestHandler->handle(ServerRequestFactory::fromGlobals());$emitter = new SapiEmitter();return $emitter->emit($response);

刷新浏览器,业务恢复了!这次我们用了一种更健壮的方式来处理响应。

以上代码 return 那一行是我们应用中请求/响应周期结束的地方,同时也是 web 服务器接管的地方。

总结

现在你已经获得了现代化的 PHP 代码。 仅仅 44 行代码,在几个被广泛使用,经过全面测试和拥有可靠互操作性的组件的帮助下,我们就完成了一个现代化 PHP 程序的引导。它兼容 PSR-4, PSR-7,PSR-11 以及 PSR-15,这意味着你可以使用自己选择的其他任一供应商对这些标准的实现,来构建自己的 HTTP 消息, DI 容器,中间件,还有中间件调度器。

我们深入理解了我们决策背后使用的技术和原理,但我更希望你能明白,在没有框架的情况下,引导一个新的程序是多么简单的一件事。或许更重要的是,我希望在有必要的时候你能更好的把这些技术运用到已有的项目中去。

你可以在 ramework”>这个例子的 GitHub 仓库 上免费 fork 和下载它。

如果你正在寻找更高质量的解耦软件包资源,我衷心推荐你看看 Aura, 了不起的软件包联盟, Symfony 组件, ramework.github.io/”>Zend framework 组件,Paragon 计划的聚焦安全的库, 还有这个 关于 PSR-15 中间件的清单.

如果你想把这个例子的代码用到生产环境中, 你可能需要把路由和 容器定义 分离到它们各自的文件里面,以便将来项目复杂度提升的时候更好维护。我也建议 ramework.zend.com/blog/2017-09-14-diactoros-emitters.html”>实现 EmitterStack 来更好的处理文件下载以及其他的大量响应。

以上就是教你在不使用框架的情况下也能写出现代化 PHP 代码的详细内容,更多请关注创想鸟其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/1258576.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2025年12月10日 05:49:10
下一篇 2025年12月10日 05:49:19

相关推荐

  • HTMLrev 上的免费 HTML 网站模板

    HTMLrev 是唯一的人工策划的库专门专注于免费 HTML 模板,适用于由来自世界各地慷慨的模板创建者制作的网站、登陆页面、投资组合、博客、电子商务和管理仪表板世界。 这个人就是我自己 Devluc,我已经工作了 1 年多来构建、改进和更新这个很棒的免费资源。我自己就是一名模板制作者,所以我知道如…

    2025年12月24日
    300
  • 如何使用 Laravel 框架轻松整合微信支付与支付宝支付?

    如何通过 laravel 框架整合微信支付与支付宝支付 在 laravel 开发中,为电商网站或应用程序整合支付网关至关重要。其中,微信支付和支付宝是中国最流行的支付平台。本文将介绍如何使用 laravel 框架封装这两大支付平台。 一个简单有效的方法是使用业内认可的 easywechat lara…

    2025年12月24日
    000
  • Laravel 框架中如何无缝集成微信支付和支付宝支付?

    laravel 框架中微信支付和支付宝支付的封装 如何将微信支付和支付宝支付无缝集成到 laravel 框架中? 建议解决方案 考虑使用 easywechat 的 laravel 版本。easywechat 是一个成熟、维护良好的库,由腾讯官方人员开发,专为处理微信相关功能而设计。其 laravel…

    2025年12月24日
    300
  • 如何在 Laravel 框架中轻松集成微信支付和支付宝支付?

    如何用 laravel 框架集成微信支付和支付宝支付 问题:如何在 laravel 框架中集成微信支付和支付宝支付? 回答: 建议使用 easywechat 的 laravel 版,easywechat 是一个由腾讯工程师开发的高质量微信开放平台 sdk,已被广泛地应用于许多 laravel 项目中…

    2025年12月24日
    000
  • 使用Laravel框架如何整合微信支付和支付宝支付?

    使用 Laravel 框架整合微信支付和支付宝支付 在使用 Laravel 框架开发项目时,整合支付网关是常见的需求。对于微信支付和支付宝支付,推荐采用以下方法: 使用第三方库:EasyWeChat 的 Laravel 版本 建议直接使用现有的 EasyWeChat 的 Laravel 版本。该库由…

    2025年12月24日
    000
  • 如何将微信支付和支付宝支付无缝集成到 Laravel 框架中?

    如何简洁集成微信和支付宝支付到 Laravel 问题: 如何将微信支付和支付宝支付无缝集成到 Laravel 框架中? 答案: 强烈推荐使用流行的 Laravel 包 EasyWeChat,它由腾讯开发者维护。多年来,它一直保持更新,提供了一个稳定可靠的解决方案。 集成步骤: 安装 Laravel …

    2025年12月24日
    100
  • css中的浏览器私有化前缀有哪些

    css中的浏览器私有化前缀有:1、谷歌浏览器和苹果浏览器【-webkit-】;2、火狐浏览器【-moz-】;3、IE浏览器【-ms-】;4、欧朋浏览器【-o-】。 浏览器私有化前缀有如下几个: (学习视频分享:css视频教程) -webkit-:谷歌 苹果 background:-webkit-li…

    2025年12月24日
    300
  • 如何利用css改变浏览器滚动条样式

    注意:该方法只适用于 -webkit- 内核浏览器 滚动条外观由两部分组成: 1、滚动条整体滑轨 2、滚动条滑轨内滑块 在CSS中滚动条由3部分组成 立即学习“前端免费学习笔记(深入)”; name::-webkit-scrollbar //滚动条整体样式name::-webkit-scrollba…

    2025年12月24日
    000
  • css如何解决不同浏览器下文本兼容的问题

    目标: css实现不同浏览器下兼容文本两端对齐。 在 form 表单的前端布局中,我们经常需要将文本框的提示文本两端对齐,例如: 解决过程: 立即学习“前端免费学习笔记(深入)”; 1、首先想到是能不能直接靠 css 解决问题 css .test-justify { text-align: just…

    2025年12月24日 好文分享
    200
  • 关于jQuery浏览器CSS3特写兼容的介绍

    这篇文章主要介绍了jquery浏览器css3特写兼容的方法,实例分析了jquery兼容浏览器的使用技巧,需要的朋友可以参考下 本文实例讲述了jQuery浏览器CSS3特写兼容的方法。分享给大家供大家参考。具体分析如下: CSS3充分吸收多年了web发展的需求,吸收了很多新颖的特性。例如border-…

    好文分享 2025年12月24日
    000
  • 360浏览器兼容模式的页面显示不全怎么处理

    这次给大家带来360浏览器兼容模式的页面显示不全怎么处理,处理360浏览器兼容模式页面显示不全的注意事项有哪些,下面就是实战案例,一起来看一下。  由于众所周知的情况,国内的主流浏览器都是双核浏览器:基于Webkit内核用于常用网站的高速浏览。基于IE的内核用于兼容网银、旧版网站。以360的几款浏览…

    好文分享 2025年12月24日
    000
  • 如何解决css对浏览器兼容性问题总结

    css对浏览器的兼容性有时让人很头疼,或许当你了解当中的技巧跟原理,就会觉得也不是难事,从网上收集了ie7,6与fireofx的兼容性处理方法并 整理了一下.对于web2.0的过度,请尽量用xhtml格式写代码,而且doctype 影响 css 处理,作为w3c的标准,一定要加 doctype声名.…

    好文分享 2025年12月23日
    000
  • 关于CSS3中选择符的实例详解

    英文原文: www.456bereastreet.com/archive/200601/css_3_selectors_explained/中文翻译: www.dudo.org/article.asp?id=197注:本文写于2006年1月,当时IE7、IE8和Firefox3还未发行,文中所有说的…

    好文分享 2025年12月23日
    000
  • 阐述什么是CSS3?

    网页制作Webjx文章简介:CSS3不是新事物,更不是只是围绕border-radius属性实现的圆角。它正耐心的坐在那里,已经准备好了首次登场,呷着咖啡,等着浏览器来铺上红地毯。            CSS3不是新事物,更不是只是围绕border-radius属性实现              …

    好文分享 2025年12月23日
    000
  • 用CSS hack技术解决浏览器兼容性问题

    什么是CSS Hack?   不同的浏览器对CSS的解析结果是不同的,因此会导致相同的CSS输出的页面效果不同,这就需要CSS Hack来解决浏览器局部的兼容性问题。而这个针对不同的浏览器写不同的CSS 代码的过程,就叫CSS Hack。 CSS Hack 形式   CSS Hack大致有3种表现形…

    好文分享 2025年12月23日
    000
  • 如何使用css去除浏览器对表单赋予的默认样式

    我们在写表单的时候会发现一些浏览器对表单赋予了默认的样式,如在chorme浏览器下,文本框及下拉选择框当载入焦点时,都会出现发光的边框,并且在火狐及谷歌浏览器下,多行文本框textarea还可以自由拖拽拉大,另外还有在ie10下,当文本框输入内容后,在文本框的右侧会出现一个小叉叉,等等。不容置疑,这…

    好文分享 2025年12月23日
    000
  • jimdo能否添加html5弹窗_jimdo弹窗html5代码实现与触发条件【技巧】

    可在Jimdo实现HTML5弹窗的四种方法:一、用内置“弹窗链接”模块;二、通过HTML区块注入精简dialog结构(需配合内联CSS);三、外部托管HTML+iframe嵌入;四、纯CSS :target伪类无JS方案。 如果您希望在Jimdo网站中实现HTML5弹窗效果,但发现平台默认不支持直接…

    2025年12月23日
    000
  • jimdo如何添加html5表单_jimdo表单html5代码嵌入与字段设置【实操】

    可通过嵌入HTML5表单代码、启用字段验证属性、添加CSS样式反馈及替换提交按钮并绑定JS事件四种方式在Jimdo实现自定义表单行为。 如果您在 Jimdo 网站中需要自定义表单行为或字段逻辑,而内置表单编辑器无法满足需求,则可通过嵌入 HTML5 表单代码实现更灵活的控制。以下是具体操作步骤: 一…

    2025年12月23日
    000
  • html如何调整_调整HTML元素大小与样式属性【大小】

    可通过CSS样式属性调整HTML元素尺寸与外观:一、内联style设宽高;二、class类名调用外部CSS;三、box-sizing控制盒模型;四、相对单位实现响应式;五、transform缩放视觉尺寸。 如果您需要修改网页中某个HTML元素的尺寸或外观,可以通过CSS样式属性直接控制其宽度、高度、…

    2025年12月23日
    000
  • html5能否禁用搜索框自动填充_html5autocomplete关闭方法【教程】

    禁用HTML5搜索框自动填充有五种方法:一、设autocomplete=”off”;二、随机化name/id值;三、用无效autocomplete值如”nope”;四、JS动态设置autocomplete;五、设autocomplete=”…

    2025年12月23日
    000

发表回复

登录后才能评论
关注微信