ano-vue

an annotation vue framework

Usage no npm install needed!

<script type="module">
  import anoVue from 'https://cdn.skypack.dev/ano-vue';
</script>

README

简介

文档官网 功能简介

ano-vue脚手架工具是vue-cli3.0的超级 支持热启动,扩展功能如下:
1. 仅仅需要命令行就可以自动化创建页面,组件,以及创建其依赖关系,提高开发效率。
2. 自动化路由配置,无需手动添加路由项。
4. 动态切换代理,启动服务的时候只需要在命令行中添加需要切换的代理环境变量即可。
5. 标准化的代码及目录模版,统一前端代码风格。
6. 页面脚本按需加载,解决了单应用打包大的问题。
7. 面向对象和注解的编程体验,大大加强了代码的复用性和降低了代码的耦合度。

quick start

第一步:安装脚手架工具

windows环境需要安装可以执行linux命令行的工具,下载 gow.exe [下载地址](http://dl.pconline.com.cn/download/762799.html) 一键安装后,重新打开cmd窗口即可。
安装脚手架工具命令: npm install -gd ano-vue 

mac环境安装需要管理员权限 sudo npm install -gd ano-vue 

第二步:ano-vue -h 查看命令行

  -V, --version         output the version number
  -i,--init             初始化应用, 带应用类型参数
  -c,--create <string>  创建一个view, component, service, model
  -r,--remove <string>  删除一个view, component, service, model
  -w,--watch            启动服务器应用
  -b,--build            打包压缩静态资源生成发布包
  -h, --help            output usage information

第三步: ano-vue -i

在本地创建一个项目文件夹,cd到文件夹根目录中,执行以上命令初始化项目模板代码

第四步:npm install -d

安装package.json中的模块依赖

第五步:ano-vue -w

启动项目, 会看到一个网站的初始化页面模板,表示初步运行已经成功,如果你要开发自己的项目可以修改下index.html将模板代码修改下即可 ano-vue -w dev 表示启动服务并使用proxy.config.js中的dev代理。

*项目核心目录文件介绍

1. proxy.config.js 配置服务端ajax请求代理文件,使用的时候只需要 ano-vue -i dev(说明:这里的参数为需要切换代理项的键)。
2. main.js webpack项目打包入口文件
3. src/assets 存放图片和静态文件的目录。
4. src/common 项目的公共文件夹
5. src/common/components 全局vue组件目录其中BaseComponent 为所有组件的基类,可以为所有组件增加公共功能。
6. src/controller/index.js 路由文件,拦截用户请求,这里和 vue-router的配置文件一样,使用脚手架会自动更新这个文件内容,大部分情况下不需要用户自动修改,除非配置拦截器或者子路由。
7. src/model 客户端向服务端发送ajax请求获取数据的实体类文件夹。
8. src/service 通用业务功能的实体类存放目录,为view层提供微服务功能模块。
9. src/view 页面入口组件的存放目录。 

看到这里,我们开始一个麻雀虽小五脏俱全的入门级练习。练习的内容包括以下几个功能点:

1. 创建一个页面组件 list
2. 在list中使用vuex的状态管理器显示一段内容
3. 创建model实体,在list中调用model实体的 showList方法向后台发送ajax请求获取数据
4. 创建一个service的切面为model实体的showList方法增加执行前和执行后的拦截功能
5. 在list页面组件中使用 @provider依赖注入将 model和service自动绑定进来,这个前提是model和service都是autowire
(自动装载类)。
6. 创建list页面的私有子组件banner 和 通用组件 slider
7. 将list组件的数据传递给子组件banner 在banner中使用 @props注解获取接受数据

接下来我们就开始练习吧!

第一步:创建页面 list.vue

使用命令: ano-vue -c view list
这个命令的意思是 创建一个视图层的页面 list 

我们打开 src/view/list/list.vue源码来简单分析下:

    import {component,store} from '@common/lib/decorator'
    import BaseComponent from '@common/components/BaseComponent'
    import listStore from './store'
    @component
    @store(listStore)
    export default class list  extends BaseComponent {
        constructor() {
            super();
        }
        data() {
            return {
                
            }
        }
        created() {
            
        }
        mounted() {
         
        }
        methods() {
            return {
               
            }    
        }
    }
1. 在使用注解的时候首先需要将 decorator这个类引入进来,用到哪个注解就解构这个注解中的方法即可。
2. BaseComponent 为当前组件类的基类,比如我想为所有组件增加一个 hide和show方法来在当前组件中仅仅使用this.show就能显示当前组件,this.hide就能隐藏组件这样的好处是相当于在 Vue.prototype上挂在原型方法基本是一个道理。
3. @component注解表明当前类是一个vue的组件类。
4. @store(listStore) 将当前vuex的store模块注入到全局 当然你也可以给它取个别名例如: @store("userStore", listStore); 使用的时候可以用 this.$store.state.userStore.getters 或者 this.$store.state.listStore.getters 这个可以自己尝试下。
5. 类中的生命周期函数,与原来的对象形式基本是一样的。接下来我把常用的生命周期函数一一列出如下:
       data() {
            return {
                "username": "ue2"
            }
        }
        created() {
            
        }
        computed() {
            return {
                
            }
        }
        components() {
            return {
                
            }
        }
        watch() {
            return {
               
            }
        }
        filters() {
            return {
                
            }
        }
        methods() {
            return {
               
            }    
        }
        mounted() {
         
        }
        beforeMount() {

        } 

第二步:在list目录下的store.js中增加一个state名字为sex值为male

export default {
    namespaced : true,
    state : {
        sex: "male"
    },
    mutations : {
        
    },
    actions : {
        
    },
    getters : {
      
    }
}

第三步:在list.vue中进行显示

<template>
    <div>
        {{$store.state.listStore.sex}}
    </div>
</template>

第四步:创建一个user的实体类model

ano-vue -c model user

此时会在src/model文件夹下自动生成一个 user.js的model实体代码如下:
import {autowire,model,requestMapping} from '@common/lib/decorator.js'
import Base from './base'
@autowire({moduleId:"user"})
@model
export default class user extends Base {
    constructor() {
        super();
    }
}
代码解释:
@autowire({moduleId:"user"}) 自动装在当前类 其中参数moduleId是必填的这里的moduleId 是与 @provider(["user"])对应的,只有自动装在的类,才可以使用 @provider进行依赖注入。
这里还要强调一个额外的功能,除了moduleId意外例如我们给这个类增加一个属性参数name 代码如下:

import {autowire,model,requestMapping} from '@common/lib/decorator.js'
import Base from './base'
@autowire({moduleId:"user", name: "猪八戒"})
@model
export default class user extends Base {
    name = ""
    constructor() {
        super();
    }
}
我们可以通过以上的代码在自动装载当前类的时候给name初始化一个值,还是比较强大的吧。

接下来我们为这个model增加一个showUserList的方法并且可以往服务端发送请求代码如下:
import {autowire,model,requestMapping} from '@common/lib/decorator.js'
import Base from './base'
@autowire({moduleId:"user"})
@model
export default class user extends Base {
    constructor() {
        super();
    }
    @requestMapping({url: "/api/v1/showUserList", type: "get"})
    getUserList(req, res) {
        return res;
    }
}
代码解释: 使用 @requestMapping注解可以表明当前的showUserList 会自动想服务端发送url的请求 类型为get,默认为get请求,return res(一个包装了返回数据的promise对象) req参数为调用方传入的json参数。
在list.vue中调用model中的这个方法代码如下:

import {component,store,provider} from '@common/lib/decorator'
    import BaseComponent from '@common/components/BaseComponent'
    import listStore from './store'
    @component
    @store(listStore)
    @provider(["user"])
    export default class list  extends BaseComponent {
        constructor() {
            super();
        }
        data() {
            return {
                
            }
        }
        created() {
            this.user.getUserList().then((res)=>{
                console.log(res);
            }) 
        }
        mounted() {
         
        }
        methods() {
            return {
               
            }    
        }
    }
代码解释: 在@provider中进行依赖注入,在create钩子函数中进行调用。很简单吧

第五步:创建一个面向切面编程的 aop service

ano-vue -c service log

此时在src/service目录中生成了一个aop的service代码如下:

import {autowire} from '@common/lib/decorator.js'
@autowire({"moduleId": "log"})
export default class log {
    
}
这个service的功能是,我们期望在getUserList之前记录下代码执行的starttime,在函数执行完成以后记录一个endTime。
import {autowire,aspect,before,after} from '@common/lib/decorator.js'
@autowire({"moduleId": "log"})
@aspect
export default class log {
    @before
    recordExecBeforeTime() {

    }
    @after
    recordExecAfterTime() {

    }
}
代码解释:
1. 增加@aspect注解表明这个类为一个切面, @before @after 可以是多个,按照顺序执行

接下来我们在model的user中应用这个切面代码如下:

import {autowire,model,requestMapping,inject,agent} from '@common/lib/decorator.js'
import Base from './base'
@autowire({moduleId:"user"})
@model
@agent
export default class user extends Base {
    constructor() {
        super();
    }
    @inject("log")
    @requestMapping({url: "/api/v1/showUserList", type: "get"})
    getUserList(req, res) {
        return res;
    }
}
代码解释:要在类上使用切面,必须要有这些元素: @agent 被动态代理注解 @inject 在那个方法上使用切面。 

第六步:创建一个list.vue的私有子组件banner

ano-vue -c component list/banner

此时会在 src/view/list/components 下面自动生成一个banner.vue的子组件

在list.vue中引入私有子组件代码如下:
    import {component,store,provider} from '@common/lib/decorator'
    import BaseComponent from '@common/components/BaseComponent'
    import listStore from './store'
    import banner from './components/banner'
    @component
    @store(listStore)
    @provider(["user"])
    export default class list  extends BaseComponent {
        constructor() {
            super();
        }
        data() {
            return {
                
            }
        }
        created() {
            this.user.getUserList().then((res)=>{
                console.log(res);
            }) 
        }
        mounted() {
         
        }
        components() {
            return {
                banner
            }
        }
        methods() {
            return {
               
            }    
        }
    }

第七步:创建一个list.vue的通用子组件slider

ano-vue -c component common/slider

通过以上命令会在 src/common/components 目录下自动生成 slider.vue
在list.vue中引入代码如下:
    import {component,store,provider} from '@common/lib/decorator'
    import BaseComponent from '@common/components/BaseComponent'
    import listStore from './store'
    import banner from './components/banner'
    import slider from '@common/components/slider'
    @component
    @store(listStore)
    @provider(["user"])
    export default class list  extends BaseComponent {
        constructor() {
            super();
        }
        data() {
            return {
                
            }
        }
        created() {
            this.user.getUserList().then((res)=>{
                console.log(res);
            }) 
        }
        mounted() {
         
        }
        components() {
            return {
                banner,
                slider
            }
        }
        methods() {
            return {
               
            }    
        }
    }

第八步: 在list.vue中给banner.vue子组件传递参数

list.vue 传值代码如下:

<template>
    <div>
        {{$store.state.listStore.sex}}
        <banner :username="username"></banner>
        <slider></slider>
    </div>
</template>

banner.vue 接受参数代码如下:

    import {component, props} from '@common/lib/decorator'
    import BaseComponent from '@common/components/BaseComponent'
    @component
    @props({"username": String})
    export default class banner  extends BaseComponent {
        constructor() {
            super();
        }
        data() {
            return {
                
            }
        }
        created() {
            
        }
        mounted() {
         
        }
        methods() {
            return {
               
            }    
        }
    }
代码解释: 这里使用了 @props 进行参数接受,我们可以为被接受的参数指定一种数据类型进行校验.

webpack中的别名定义如下:

resolve: {
    alias: {
      'vue

: 'vue/dist/vue.esm.js',
      '@assets': path.resolve(__dirname, 'src', 'assets'),
      '@common': path.resolve(__dirname, 'src', 'common'),
      '@controller': path.resolve(__dirname, 'src', 'controller'),
      '@model': path.resolve(__dirname, 'src', 'model'),
      '@service': path.resolve(__dirname, 'src', 'service'),
      '@view': path.resolve(__dirname, 'src', 'view'),
    },
    extensions: ['*', '.js', '.vue', '.json']
  }

最后再次介绍两个命令:

ano-vue -w 启动服务
ano-vue -w dev 启动服务并使用proxy.config.js中的dev代理
ano-vue -b 打包应用 

如何创建二级路由?

  ano-vue -c component list/banner router 
  使用以上命令会自动更新 controller/index.js 中的路由配置,自动添加children子路由项。
  ano-vue -r component list/banner router  自动删除子路由项

到此为止你已经可以入门了,如果有任何问题可以通过以下方式联系作者

QQ:912273637 技术交流群:849829771