Wait the light to fall

第九天 - 为你的 Mojolicious 应用添加主题系统

焉知非鱼

img

你写了一个很棒的Mojolicious应用程序,人们使用它。奇妙!但是用户可能想要修改应用程序的主题:更改徽标,使用其他CSS框架,这类事情。

修改Mojolicious应用程序的主题非常简单:在公共和模板中添加,修改或删除内容。但是所有这些直接修改可能无法在更新应用程序时继续存在:它们只会被新版本的文件删除。

让我们看看我们如何提供一种在Mojolicious应用程序中拥有主题系统的方法,该方法允许用户在没有痛苦的情况下拥有自定义主题,并且没有丢失更新的风险。

一个新的应用程序 #

当您使用mojo生成MyApplication创建新的Mojolicious应用程序时,这些是将提供文件及其默认内容的默认目录:

$ tree public templates
public
└── index.html
templates
├── example
│   └── welcome.html.ep
└── layouts
    └── default.html.ep

2 directories, 3 files

public是存储静态文件的地方,而templates是存储模板的地方。

这些路径在$ app-> static-> paths和$ app-> renderer-> paths中的Mojolicious应用程序中注册。幸运的是,这两个对象是数组引用,因此我们可以向它们添加或删除目录。

当提供静态文件时,我们的应用程序在$ app-> static-> paths数组的第一个目录中搜索该文件,如果找不到它,则搜索下一个目录,依此类推。模板渲染也是如此。

让我们改变路由 #

我们可以将公共模板和模板默认目录保存在应用程序目录的根目录下,但我喜欢在一个名为themes的目录中重新组合所有与主题相关的东西并调用我的默认主题…好吧,默认。

创建新目录并在其中移动默认主题目录:

$ mkdir -p themes/default
$ mv public templates themes/default

然后,我们需要更改应用程序中的路径。在 lib/MyApplication.pm 中添加:

# Replace the default paths
$self->renderer->paths([$self->home->rel_file('themes/default/templates')]);
$self->static->paths([$self->home->rel_file('themes/default/public')]);

添加使用其他主题的方法 #

如前所述,Mojolicious在已注册路径的第一个目录中搜索静态文件或模板,如果找不到文件或模板则转到下一个。

因此,我们需要在默认主题路径之前添加新主题路径。

假设我们创建了一个圣诞主题,其中文件位于主题/圣诞节/公共内容中,哪些模板位于主题/圣诞节/模板中。

我们要添加到代码中的代码段变为:

# Replace the default paths
$self->renderer->paths([$self->home->rel_file('themes/default/templates')]);
$self->static->paths([$self->home->rel_file('themes/default/public')]);
# Put the new theme first
unshift @{$self->renderer->paths}, $self->home->rel_file('themes/christmas/templates');
unshift @{$self->static->paths},   $self->home->rel_file('themes/christmas/public');

通过这种方式,我们可以重载默认文件。

您不必修改默认主题的每个文件以具有新主题:只需在新主题目录中复制要重载的文件,然后使用它而不是默认主题目录。

假设你的默认主题中有一个background.png文件:

$ cd themes/default
$ tree public templates
public
├── background.png
└── index.html
templates
├── example
│   └── welcome.html.ep
└── layouts
    └── default.html.ep

2 directories, 4 files

为了超载它,你只需要这个:

$ cd themes/christmas
$ tree public templates
public
└── background.png
templates

0 directories, 1 files

使用 Mojolicious::Plugin::Config 插件 #

Mojolicious::Plugin::Config自带Mojolicious,是让用户配置应用程序的好方法。为什么不用它让他们选择他们想要的主题?在我们的示例中,该设置将毫不奇怪地命名为主题。

首先,使用插件:

# Mojolicious
my $config = $app->plugin('Config' => {
    default => {
        theme => 'default'
    }
});

请注意,我在插件的配置中添加了默认值。它确保即使用户没有选择主题,我们也会为所选主题设置正确的值。

现在,我们只需在代码中使用该配置设置:

# Replace the default paths
$self->renderer->paths([$self->home->rel_file('themes/default/templates')]);
$self->static->paths([$self->home->rel_file('themes/default/public')]);
# Do we use a different theme?
if ($config->{theme} ne 'default') {
    # Put the new theme first
    my $theme = $self->home->rel_file('themes/'.$config->{theme});
    unshift @{$self->renderer->paths}, $theme.'/templates' if -d $theme.'/templates';
    unshift @{$self->static->paths},   $theme.'/public'    if -d $theme.'/public';
}

请注意 if -d $theme.'/templates':如果使用主题名称中的拼写错误并且如果您只需要其中一个,则可以避免在主题目录中创建 templatespublic,从而防止出现问题。

结论 #

您现在正在应用程序中提供主题系统。用户现在可以改变它的样式而不用担心丢失对更新的更改(尽管他们需要检查他们所做的更改,以防默认主题发生很大变化)。

您甚至可以自己提供不同的主题,就像我为我的 URL 缩短应用程序 Lstu 所做的那样.🙂