浅入深出Vue:代码整洁之去重

在开始本篇的主题以前,让咱们把上次遗留下来的问题都清理一下:javascript

  • 将其余组件中 axios 请求的地方封装起来。

这里就不把代码放在开头了,相关代码都放在文末,有兴趣了解的童鞋能够先往下翻。html

好了, 咱们如今把上篇剩下的任务给完成了,接下来咱们来正式开始本篇内容吧。vue

去重是什么

字面上意思:去除重复,在项目中,不可避免的会出现重复代码。可是若是很差好去处理这些重复代码,那颇有可能就会给你不少“惊喜”。java

如何为“重复” 下一个定义呢?ios

从最浅显的层次来看, 相同便是重复。在咱们上面的代码中,每个组件中都有这么一行代码:git

import RequestSender from '@/requestSender';

这就是重复代码,在每个须要发起请求的组件中你都会须要写上这么一行代码。那么让咱们就这个列举一些可能出现的问题:数据库

  • 某一天修改了文件名axios

  • 某一天移动了该文件后端

那么项目中须要修改的地方将会是多少呢?而在修改中会产生手误的几率又会是多少呢?以上仍是在单人开发的时候,若是团队协做开发,这些状况的几率又会是什么样的呢。api

如何去重

固然,对于上面这种引入型的代码,相似移动文件,修改文件名这种操做。IDE 就能很好的帮你处理,好比 WebStorm 若是你使用重构相关的功能去重命名,那么它会找出全部 “疑似”引用的代码片断,你能够选择全部相关的引用同时修改。

这是一种手段,很好的解决了上面这些问题。

那么让咱们来看看另外一个重复代码的问题:

class RequestSender {
    static GetBlogList() {
        return axios.get('https://451ece6c-f618-436b-b4a2-517c6b2da400.mock.pstmn.io/list');
    }

    static Publish(data) {
        return axios.post('https://451ece6c-f618-436b-b4a2-517c6b2da400.mock.pstmn.io/publish', data);
    }

    static Login(data) {
        return axios.post('https://451ece6c-f618-436b-b4a2-517c6b2da400.mock.pstmn.io/login', data);
    }

    static Signup(data) {
    
        return axios.post('https://451ece6c-f618-436b-b4a2-517c6b2da400.mock.pstmn.io/signup', data);
    }
}

上面的代码, 重点不在函数噢。 仔细看看它们有哪些地方重复了。

光从代码上来看,其实有不少“重复”的地方,好比说 returnstaticaxios.getaxios.post

这些重复有一部分是语法,有一部分是调用。这些都是不可避免的,所以这些重复代码并不在咱们须要重构的范围内。那么,到底是哪段代码呢?

https://451ece6c-f618-436b-b4a2-517c6b2da400.mock.pstmn.io

准确来讲,它并不算是代码。而是“硬编码”,从总体代码上来看,这是目前全部后台接口的域名

在开发过程当中,通常来讲至少是会有两个环境存在:开发环境、线上环境。而它们两的后台接口域名通常而言又不会重复,难道每次发布前都手动改一下域名么?

咱们先来列举一下可能会出现的问题:

  • 开发环境、线上环境域名不一致

  • 团队协做中,开发者之间的开发域名不一致

  • 当线上/开发 环境中的域名须要修改时

能够看到,当遇到上述问题时,项目中全部硬编码了域名的地方都是须要修改的,那么为何要修改呢?

除了解决上面列举的具体问题以外,最根本的目的是:

  • 保持惟一性

若是有两段/多段代码它们表示的含义彻底一致,而且从目的上来讲也是一致的。那么就应该尽量将其只保留一处定义。

那么对于这个域名咱们怎么处理呢?首先将其提炼出来:

static Host = 'https://451ece6c-f618-436b-b4a2-517c6b2da400.mock.pstmn.io';

这样,引用的地方就能够这么写:

static GetBlogList() {
    return axios.get(`${Host}/list`);
}

这样,当发现修改的时候,是否是只须要修改 Host 这么一个地方就行了呢?、

可是这样还存在问题,若是要发布,或者是在 gitsvn上协做的时候呢? 每一个人、每一个环境都须要修改这个变量,而且还要在提交代码时移除掉本身的修改以免冲突。

可配置化

Host 的例子是很是常见的,当咱们须要发布、团队协做的时候,环境不一样是很是常见的,有可能在本身电脑上 Hostlocalhost:8080,换在另外一我的电脑上就是 localhost:9099了。那么线上环境有可能又是 xxx.xxx.comxx.xxx.com/api诸如此类。

这里若羽实践的解决方案是:

  • 将与环境相关的硬编码提炼成可配置项放入配置文件

  • 配置文件模板化

  • 配置模板文件多样化

真正的配置文件是不会被提交上去,只有一个模板文件。因为配置文件并不会被提交,因此开发者之间的环境差别就能够忽略了,你们根据本身的环境修改配置文件便可。

那么对于线上环境、测试环境等等,创建对应的配置文件模板便可。当发布时,使用对应环境的发布配置文件模板做为配置文件便可。

那么咱们来实践一下:

新建配置模板文件 config.js.template:

const config = {
    HOST: '',
};

export default config;

接下来复制粘贴模板文件,并重命名为 config.js:

const config = {
    HOST: 'https://451ece6c-f618-436b-b4a2-517c6b2da400.mock.pstmn.io',
};

export default config;

接下来修改一下 requestSender.js:

import axios from 'axios';
import config from '@/config.js';

class RequestSender {
    static GetBlogList() {
        return axios.get(`${config.HOST}/list`);
    }

    static Publish(data) {
        return axios.post(`${config.HOST}/publish`, data);
    }

    static Login(data) {
        return axios.post(`${config.HOST}/login`, data);
    }

    static Signup(data) {
    
        return axios.post(`${config.HOST}/signup`, data);
    }
}

export default RequestSender;

好了,如今不论是在任何一个环境下,均可以游刃有余的切换域名了。并且这里面还有一个颇有意思的事情:

  • 全部的改动对于表现层而言是透明的。

简单来讲,咱们在这里重构了这么多的代码,然而咱们并不须要修改任何一个视图组件中的代码!!!

表面上仍是原来的样子,可实际上已经“打扫”过了。这也是重构中须要注意的一点:

  • 步子迈小一点,迈准一点

写在后面

上篇中有人问到若羽说封装请求的意义何在,axios 自己就是带着 Promise的支持了。

这里对这个问题作一个回应,立场仅表明若羽本人,并不为任何人“作表明”:

  1. 封装并不是为了 Promise,而是为了将“发送请求”的这个动做封装起来。由于这属于数据获取的行为,然后面 then 里的逻辑其实是和业务挂钩:为视图设置数据。这是两个不一样的行为,就像后端同样:ORM它仅仅是负责从数据库中取数据而已,真正对这个数据进行逻辑操做的,并非它。这也是接下来博文的主题:专注,一个函数应当只负责一件事情。

  2. 这一篇文章便表示了另外一层意思:去重,在第一层封装的过程当中咱们发现了域名的硬编码问题(不封装也是同样),所以在这里若是不作封装的话,即便将域名提炼出来,涉及到修改的文件一样也会较多。不过这种修改是一次性的。

以上即是若羽对上一篇中示例的解释。

欢迎你们发表评论,共同探讨。

上篇重构代码

edit.vue:

<script>
    import RequestSender from '@/requestSender'
    export default {
        name: "Edit",
        data() {
            return {
                model: {
                    title: '',
                    content: '',
                }
            }
        },
        methods: {
            submit() {
                RequestSender.Publish(this.model)
                    .then(res => {
                         if(res.data.Code === 200) {
                             this.$message.success('发布成功');
                         }
                     })
            }
        }
    }
</script>

Login.vue:

<script>
    import RequestSender from '@/requestSender';
    export default {
        name: "Login",
        data() {
            return {
                model: {
                    username: '',
                    password: '',
                }
            }
        },

        methods: {
            submit() {
                RequestSender.Login(this.model)
                    .then(res => {
                        if(res.data.Code === 200) {
                            this.$message.success('登陆成功');
                        }
                    })
            }
        }
    }
</script>

Signup.vue:

<script>
    import RequestSender from '@/requestSender';

    export default {
        name: "Signup",
        data() {
            return {
                model: {
                    username: '',
                    password: '',
                    rePassword: ''
                }
            };
        },
        methods: {
            submit() {
                if(this.model.password !== this.model.rePassword){
                    this.$message.error('两次出入密码不一致.');
                    return ;
                }

                RequestSender.Signup(this.model)
                    .then(res => {
                        if(res.data.Code === 200){
                            this.$message.success("注册成功");
                            this.$router.push('./login');
                        }
                    });
            }
        }
    }
</script>

requestSender.js:

import axios from 'axios';

class RequestSender {
    static GetBlogList() {
        return axios.get('https://451ece6c-f618-436b-b4a2-517c6b2da400.mock.pstmn.io/list');
    }

    static Publish(data) {
        return axios.post('https://451ece6c-f618-436b-b4a2-517c6b2da400.mock.pstmn.io/publish', data);
    }

    static Login(data) {
        return axios.post('https://451ece6c-f618-436b-b4a2-517c6b2da400.mock.pstmn.io/login', data);
    }

    static Signup(data) {
    
        return axios.post('https://451ece6c-f618-436b-b4a2-517c6b2da400.mock.pstmn.io/signup', data);
    }
}

export default RequestSender;
相关文章
相关标签/搜索