thinkjs+vue+elementui初探

thinkjs+vue+elementui初探

月光魔力鸭

2020-01-10 00:12 阅读 1181 喜欢 1 elementui thinkjs vue

之前看知乎相中了一个想法,给宝宝做一个站,上传生活的日常照片啊、视频之类的,存储肯定是在自己家里,然后做个穿透这样..开始做的时候又想着是时候接触下这些东西了,虽然公司都一点不用,但是自己没事接触下拓展下也是好的。

看来看去感觉还是vue相对简单一些,不过从开始搞这个到真正的继续下去,中间还是经历了不少,毕竟很多东西都没接触过,直接上手自我感觉难度不小。

es6 webpack vue elementui,其中 es6elementui相对简单一些,UI框架直接复制就好,看下API感觉问题不是很多,最麻烦的我感觉就是webpack了,虽然只是一个打包工具,但是涉及到的东西比较多,又记不住,每次都要现查文档,之前陆陆续续用过一小部分,现在再看还是不记得。最终还是放弃了这部分,直接用的vue-cli ,这个更简单..(额,不能说简单,应该是压根就没有接触到)

先讲下自己的大体思路,中间陆陆续续 从github上down了几个小项目参考。

后端thinkjs来做服务端,提供数据接口,这块这里讲的可能不多,虽然我也不熟练,不过还好用过几次了,需要啥直接查API了,不过本文中会讲到关于jwt的问题。

架子

开发环境直接使用前后分离,至于上到生产环境后,我还是想都放在一个项目中,合并一下。

环境搭建

服务端

直接通过thinkjs 命令行来创建项目。

thinkjs new baby
-- 选择对应的选项即可

数据库使用mysql ,表结构很简单,有四张表,nas_attach 附件表 nas_member成员表 nas_record 记录主表 nas_record_attach 记录-附件关系表,就不写表格了,直接上图。

nas_attach

nas_member

nas_record

nas_record_attach

通过命令创建项目后,修改对应的数据库链接,然后启动:

npm start
前端

前端我是直接通过vue-cli生成的,最开始是自己手动配置的webpack ,虽然最终也跑起来了,但是后边遇到一个问题elementui 2.13.0版本的table 不显示数据,至于为啥我也不清楚,换了一个低版本的可以,但是后来想应该是我配置的问题,又找不到哪里的问题,最终就直接用了命令行创建了,原来的索性不要了。

参考官方文档

vue  create admin

生成后运行npm run serve 就把前端跑起来了。

开发中

由于是第一次使用vue来写小东西,很多内容也没搞明白,啥原来也不知道,用的很浅,但是里面的router就折腾了我一阵子,参考的github项目勉勉强强写了出来。(将近用了2天才大体整明白来来回回的逻辑)

问题1 : 前端登录验证

由于是前端单独跑的,当时还想了好一阵子怎么来控制,后来看了下别人的项目,发现基本都是靠localStorage来判断的,当然自己也没想到其他好的主意。

//在main.js 中通过对router狗子函数处理,来进行登录跳转
router.beforeEach((to, from, next) => {
//to.meta.title 是router.js中配置的,用来修改页面标题。
    document.title = `${to.meta.title} | 采然一刻`;
    const user = localStorage.getItem('local_user');
    if(!user && to.path !== '/login'){
        next('/login');
    }else{
        next();
    }
});

然后,在登录成功后,写入local_user ,当超时或退出的时候,清空该数据。

问题2: router 跳转

使用的elementui的导航。

<template>
    <el-container>
        <el-header>
            <el-menu router background-color="#409EFF" text-color="#fff" active-text-color="#F56C6C" unique-opened :default-active="onRoutes" mode="horizontal" @select="handleSelect">
                <el-menu-item index="/home">首页</el-menu-item>
                <el-menu-item index="/member">家庭成员</el-menu-item>
                <el-menu-item index="/record">生活记录</el-menu-item>
            </el-menu>
        </el-header>
        <el-main>
            <transition>
                <router-view></router-view>    
            </transition>
        </el-main>
    </el-container>
</template>
<script>

import '@/assets/css/home.css'
export default {
    data() {
        return {
            activeIndex: 'index',
            msg: 'Index data'
        }
    },
    computed: {
        onRoutes() {
            let r = this.$route.path.replace('/', '').split('/')[0];
            console.log(r);
            return '/'+r;
        }
    },
    methods: {
        handleSelect(key, keyPath) {
            console.log(key, keyPath);
        }
    },
    created() {
        console.log('mounted');
    }
}
</script>
<style scoped>
.el-header{
    padding:0px;
}
    </style>

这里面,可能会困扰的就是,怎么让页面默认是当前选中的菜单项,通过this.$route.path 来进行判断处理。

import Vue from 'vue';
import Router from 'vue-router';

Vue.use(Router);

export default new Router({
    routes : [
        {
            path :'/login',
            meta : {title : '登录页面'},
            component : ()=>import('../components/page/Login.vue')
        },
        {
            path : '/',
            redirect : '/home'
        },
        {
            path : '/',
            meta : {title : '管理页面'},
            component : ()=>import('../components/page/Index.vue'),
            children : [
                {
                    path : 'home',
                    meta : {title : '后台管理'},
                    component : ()=>import('../components/page/Home.vue')
                },{
                    path : 'member',
                    meta : {title : '家庭成员'},
                    component : ()=>import('../components/page/Member.vue')
                },{
                    path : 'member/add',
                    meta : {title : '添加成员'},
                    component : ()=>import('../components/page/MemberAdd.vue')
                },{
                    path : 'member/add/:userId',
                    meta : {title : '编辑成员'},
                    component : ()=>import('../components/page/MemberAdd.vue')
                },{
                    path : 'record',
                    meta : {title : '生活记录'},
                    component : ()=>import('../components/page/Record.vue')
                },{
                    path : 'record/add',
                    meta : {title : '添加生活记录'},
                    component : ()=>import('../components/page/RecordAdd.vue')
                },{
                    path : 'record/add/:userId',
                    meta : {title : '编辑生活记录'},
                    component : ()=>import('../components/page/RecordAdd.vue')
                }

            ]
        },
        {
            path: '*',
            redirect: '/'
        }
    ]
});

这个router.js可能会有困扰的是,什么时候带/ 什么时候不带,children 有是什么时候用。 /是肯定要带的,但是为啥chilren里面没带,是因为子级如果带着/的话,相当于从根目录来控制的。同时children 是某个template里面的router-view。比如: app.vue 里面已经有一个router-view 来控制显示登录还是管理页面,但是管理页面又分多个页面,所以在管理页面index.vue里面还有一个router-view ,所有就有子级了。

问题3: api的鉴权

由于开发环境是前后分离,虽然生产环境就合并了,但是还是想做下接口的鉴权。简单搜索了下,基本上都是通过jwt来实现,刚好thinkjs有现成的控件了,也不用自己搞,加上就可以。 参考: https://zhuanlan.zhihu.com/p/41880306 直接使用think-session-jwt 来做配置,然后通过api调用的时候增加header来控制。当然,在使用的时候发现总是不过期,还没查看为什么。 服务端的使用就不写了,上边的文章写的很详细,直接使用session就可以了。不过要注意的是,token不正确的话,session也是可以拿到对象的,只是内容不对,要注意判断。

这里说下前端axios来带token,其实也没啥说的,找官网就完了。

import axios from 'axios'
import {baseUrl} from '../config'
axios.defaults.baseURL = baseUrl;
axios.defaults.headers.post['Content-Type'] = 'application/json';

// 添加请求拦截器
axios.interceptors.request.use(function(config) {
    let token = localStorage.getItem('local_user');
    config.headers['token'] = token||'';
    return config;
}, function(error) {
    // 对请求错误做些什么
    return Promise.reject(error);
});
// 添加响应拦截器
axios.interceptors.response.use(function(response) {
    // 对响应数据做点什么
    if(response.data.code === '-1'){//当前无权限
        //跳转到登录页面
        localStorage.removeItem('local_user');
        return Promise.reject(new Error(response.data.msg));
    }
    return response;
}, function(error) {
    // 对响应错误做点什么
    return Promise.reject(error);
});
export default axios;
问题4:图片资源的鉴权处理

最开始想的是,图片请求的时候校验下,但是图片是浏览器发出的请求,使用的img,没办法添加,又想着通过axios来获取,当然,最终没用,因为考虑到自己使用的ID,很难猜到,而且,用户就只有自己,也就放弃了。 https://cdn.pixabay.com/photo/2020/01/06/13/52/butterfly-4745417__340.jpg

未完待续。 后边,还有对图片的压缩,以及视频的第一帧获取postpath 的处理,还没完成,后边再加。

转载请注明出处: https://chrunlee.cn/article/vue-elementui-thinkjs-pc.html


感谢支持!

赞赏支持
提交评论
评论信息 (请文明评论)
暂无评论,快来快来写想法...
推荐
通过frp做穿透实现https 访问本地http项目。
功能来源于客户需求。客户有需求想把班级内所有学生的错题本生成pdf文档下载下来... 目前没有做这个功能,只有页面,还好chrome浏览器有保存pdf的功能,但是一想到这么多的学生,这么多的学科、以及这么多的参数... 还好有puppeteer
前几天同事抱怨说微博太费劲了... 一万多条记录,可能会把他累死,我心想.. 重复工作不都可以用程序代替么..
BUG 报错Tainted canvases may not be exported 。 在通过canvas 调用 toDataURL的时候出现的问题。
接下来,我们综合上面的配置,再加一个选项页面配置,做一个天气预报的小栗子。
mysql数据库插入double类型确没有小数点
ubuntu 配置nginx反向代理,这里简单记录下,后续再复习..
最近感觉docker挺好用的,由于测试服务器经常重装,这里先记录下compose文件,后边重装直接复制就行啦。