zoukankan      html  css  js  c++  java
  • vue+uikit3+laravel快速建站

    vue+uikit3+laravel快速建站

    vue+uikit3+laravel快速建站

    目前站已初步建好,待完善中,https://recallsufuture.space,源码已放到 github

    1 前言

    很早因为折腾科学上网之术,入了vps的坑,然而那个配置只是作为梯子的话实在是浪费资源, 在加上做了一阵子的web开发,却还没自己的一个站,自己的小程序做不了,网站总可以的嘛, 那么下面就开始吧。

    2 需求

    实际上还真不知到要做个什么样的网站,经过一番艰难的思考,还是决定先做已经被我做烂了的fa爬虫, 如果有其他的想法,就做成新的板块,这样就可以慢慢填坑啦。

    2.1 页面

    • 主页面,展示本站作用以及现有板块
    • fa板块,批量爬取原图链接

    3 环境

    3.1 开发环境

    • php7.2
    • npm
    • composer
    • vscode
    • redis
    • chrome & firefox

    3.2 生产环境

    • oneinstack一键环境,包括php,nginx,redis。
    • npm
    • composer

    3.3 框架

    • 前端用vue+uikit3制作足够模块化且现代化的页面,并用vue-router来提供路由支持
    • 后端用laravel,优雅且强大

    4 Let's code

    4.1 主页面

    4.1.1 界面构思

    这个页面需要有顶部导航栏,主体需要有足够大而鲜明的说明标题文字来介绍本站, 标题下面是几个card来展示现有的板块。

    4.1.2 实现

    首先是路由,默认的laravel用闭包写了一个welcome路由,这个我们不需要了,删掉routes/web.php内的这行路由, 并删掉对应的blade文件。

    因为我用了vue-router来管理路由,所以只需要在web.php中写一个拦截所有请求的路由即可,所有页面请求都导向vue页面, 即:

    Route::get('/{view?}', 'HomeController@index')->where('view', '.*')->name('home');
    

    接着修改上面的HomeController的index方法,使它返回app.blade.php模板

    <!DOCTYPE html>
    <html lang="{{ app()->getLocale() }}">
    <head>
        <meta charset="utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1">
    
        <!-- CSRF Token -->
        <meta name="csrf-token" content="{{ csrf_token() }}">
    
        <title>夙的小站</title>
    
        <!-- Styles -->
        <link href="{{ mix('css/app.css') }}" rel="stylesheet">
    </head>
    <body>
        <div id="app"></div>
    
        <!-- Scripts -->
        <script src="{{ mix('js/app.js') }}"></script>
    </body>
    </html>
    
    

    因为要用到uikit,所以去找了下脚手架,在网站根目录执行下面四条命令可以获得vue+uikit3脚手架:

    composer require laravel-frontend-presets/uikit3
    php artisan preset uikit3
    php artisan preset vue
    npm install
    

    添加vue-router路由配置文件router.js:

    import Vue from 'vue'
    import Router from 'vue-router'
    
    Vue.use(Router);
    
    export default new Router({
        mode: 'history',
        routes: [
            {
                path: '/',
                redirect: '/home',
            },
            {
                path: '/home',
                component: require('./pages/Home.vue'),
            },
        ],
    })
    
    

    修改下app.js保证编译顺利通过,然后就可以开始在resources/assets/js/pages/Home.vue里写第一个vue页面啦。

    此处省略一千字。。。直接看结果吧

    website1.png

    4.2 fa页面

    最初的想法是先将图片下到服务器,完成后打包发给用户,但实验过后发现等待时间实在太长, 一旦关了浏览器就啥都没有了,而且这样做很费服务器空间,没办法,只能退而求其次,获取来所有的链接让用户自己去下载。

    那么这个页面一共有如下几个内容:

    • 界面内需要一个表单来获取一些下载信息
    • 后台暴露出一个接口,由前端ajax访问此接口,这样可以有比较好的体验
    • 界面上要有一个公告窗口,记录当前的下载日志
    • 后台需要配合实现websocket广播功能

    前台界面的编写就不再多说,直接看下成品图 website2.png

    后台部分,首先要实现那个接口,也就是接受表单数据,处理,然后返回状态码。

    当然,还是得先把路由写好:

    <?php
    
    Route::prefix('api')->group(function () {
        // 批量获取fa链接
        Route::get('/fa', 'FaController@index')->name('fa.index');
    });
    
    // 全部拦截到此页
    Route::get('/{view?}', 'HomeController@index')->where('view', '.*')->name('home');
    

    因为可能还会有其他的api,所以我在这里分组并设置了统一的路径前缀(web.php参考了Laravel Horizon)

    然后是编写FaController,用php artisan命令创建controller,并修改其中的index方法:

    <?php
    
    namespace AppHttpControllers;
    
    use IlluminateHttpRequest;
    
    use AppEventsFaDownloadEvent;
    
    class FaController extends Controller
    {
        /**
         * 返回是否成功新建任务
         *
         * @return IlluminateHttpResponse
         */
        public function index(Request $request)
        {
            // 验证表单
            $validatedData = $request->validate([
                'id'      => "filled",
                'name'    => "required|max:255",
                'type'    => [
                    "required",
                    "regex:/gallery|scraps/"
                ],
                'pagenum' => "min:1",
                'picnum'  => "min:1|max:72",
                'maxnum'  => "min:0"
            ]);
    
            // 保存表单数据
            $id      = $validatedData['id'];
            $name    = trim($validatedData['name']);
            $type    = $validatedData['type'];
            $pagenum = $validatedData['pagenum'];
            $picnum  = $validatedData['picnum'];
            $maxnum  = $validatedData['maxnum'];
    
            event(new FaDownloadEvent($id, $name, $type, $pagenum, $picnum, $maxnum));
    
            return [
                'status' => 'ok'
            ];
        }
    }
    
    

    可以看到我先是验证了表单数据,然后将数据保存下来并触发了一个事件,验证表单数据是因为作为api, 有可能会被其他地方的代码访问,所以必须要验证数据有效性,而不直接下载改为触发事件是因为需要异步执行下载, 将下载任务放到队列里,通过广播来通知客户进度。

    这里涉及到了事件,队列和广播,通过触发事件,预先设定好的的监听器会接受事件并处理,这样可以让代码更加解耦。 队列是用来处理需要长时间运行的任务,比如发送邮件。广播是为了和让后台和浏览器即使的沟通, 利用 websocket 建立长连接,免除了ajax轮询的麻烦,具体的内容请查询laravel中文文档

    下面一个个说这些功能的实现:

    4.2.1 事件

    当前有一个FaDownloadEvent事件,这个事件接收所有表单参数,至于代码部分,其实十分的简单:

    <?php
    
    namespace AppEvents;
    
    use IlluminateBroadcastingChannel;
    use IlluminateQueueSerializesModels;
    use IlluminateBroadcastingPrivateChannel;
    use IlluminateBroadcastingPresenceChannel;
    use IlluminateFoundationEventsDispatchable;
    use IlluminateBroadcastingInteractsWithSockets;
    use IlluminateContractsBroadcastingShouldBroadcast;
    
    class FaDownloadEvent
    {
        use Dispatchable, InteractsWithSockets, SerializesModels;
    
        /**
         * Client id
         *
         * @var string
         */
        public $id;
    
        /**
         * Author name
         *
         * @var string
         */
        public $name;
    
        /**
         * Gallery or scraps
         *
         * @var string
         */
        public $type;
    
        /**
         * Start page number
         *
         * @var string
         */
        public $pagenum;
    
        /**
         * Start pic number
         *
         * @var string
         */
        public $picnum;
    
        /**
         * Max download num
         *
         * @var string
         */
        public $maxnum;
    
        /**
         * Create a new event instance.
         *
         * @return void
         */
        public function __construct($id, $name, $type, $pagenum, $picnum, $maxnum)
        {
            $this->id = $id;
            $this->name = $name;
            $this->type = $type;
            $this->pagenum = $pagenum;
            $this->picnum = $picnum;
            $this->maxnum = $maxnum;
        }
    }
    
    

    只是通过构造函数将参数保存到成员变量里而已,接下来看看接收这个事件的监听器:

    4.2.2 监听器

    <?php
    
    namespace AppListeners;
    
    use AppEventsFaDownloadEvent;
    use AppEventsDownloadStateEvent;
    use AppModelsFile;
    use AppUtilityVendorFaFurAffinityAPI;
    
    use IlluminateQueueInteractsWithQueue;
    use IlluminateContractsQueueShouldQueue;
    
    class FaDownloadListener implements ShouldQueue
    {
        /**
         * The number of seconds the job can run before timing out.
         *
         * @var int
         */
        public $timeout = 1000;
    
        /**
         * Handle the event.
         *
         * @param  FaDownloadEvent  $event
         * @return void
         */
        public function handle(FaDownloadEvent $event)
        {
            // 触发一个状态事件,此事件会向浏览器广播下面的内容
            event(new DownloadStateEvent($id, 'info', '正在下载'.$name.'/'.$type.'的第'.$nowpage.'页第'. $nowpic .'个链接'));
    
            // 下面是具体的下载逻辑,在此省略
        }
    }
    
    

    监听器类接受到事件后,就可以进行下载任务了,但是如果直接开始的话,下载过程还会是同步的, 也就是会阻塞浏览器,让它变成异步只需要简单的添加一个接口就可以啦,

    class FaDownloadListener implements ShouldQueu
    

    只要加上这个接口,任务的执行就会自动放到队列里,至于是哪个队列呢?当然是默认队列啦

    4.2.3 队列

    现在需要配置队列,队列可以看作是一个单独的进程,这个进程就是个死循环,有任务放进来就执行,没有就睡眠等待

    配置起来也不难,首先修改.env,将队列设置为redis驱动: QUEUEDRIVER=redis

    然后在网站根目录下执行: php artisan queue:worker 即可,这样就开启了一个默认的队列。 想要开启更多的不一样的队列?用 –queue 参数试试。

    不过这个进程会一直堵塞着终端,毕竟是个死循环嘛, 不想看到一直堵塞着的话可以让它后台执行: php artisan queue:worker –daemon >> /dev/null &

    这个队列配置好后,监听器就可以正常工作了,每接收到一个FaDownloadEvent事件,就会向默认队列中添加一个下载任务。

    4.2.4 广播

    现在只剩广播部分没有完成

    Date: 2018-07-26 18:36

    Author: su

    Created: 2018-07-29 日 16:00

    Validate

  • 相关阅读:
    sfs2x 连接 mongodb
    java websocket
    webstorm 4.0 注册码
    解决 sfs2 admin tool 找不到扩展
    window 注册表五大类
    opengl 学习第二日
    java google Protobuf
    扩展 java sencha touch PhonegapPlugin
    sencha touch2 kryonet socket phonegap 通信 作者:围城
    sencha touch2 layout 笔记
  • 原文地址:https://www.cnblogs.com/recallfuture/p/9373901.html
Copyright © 2011-2022 走看看