一 前言
最近做完app的一个小功能,就想年底了,做个总结吧。花了两三天的时间,断断续续分别用VUE,Angular以及小程序做了个小的todolist功能,初衷是一方面技术总结,另一方面对比它们的实现方式,进而加深对它们的理解。本来还想用react也实现一下,但由于react的all js思想,和这三个的MVVM模板思想不一样,实现方面,没有强烈的可比性,或者说易混淆性,以后有时间,单独写一下吧。
二 小程序
1 开发环境
采用微信提供的开发者工具,在官网注册开发者账号,在后台配置相应的服务域名信息。开发工具很友好,自动本地调试,真机调试等功能,有很好的兼容性。同时微信提供很多组件可以使用,使得开发小程序也更加的简单。开发思想上和vue类似,语法上有很多也很像,在主要语法章节,可以自行对比。
2 项目结构
3 主要语法
小程序和vue很多地方都很像,git上面有专门用vue开发小程序的npm包。
2.3.1 数据绑定
<input class="new-todo" value="{{ input }}"placeholder="添加事项"/>
<text class="name">{{ item.name }}</text>
2.3.2 事件绑定(只需要写函数名即可)
<text class="btn" bindtap="toggleAllHandle">切换选择全部</text>
2.3.3 属性绑定
<icon class="checkbox" type="{{ item.completed ? 'success' :'circle' }}" size='14'/>
2.3.4 条件指令
<text wx:if="{{leftCount }}">{{ leftCount }}事项可选</text>
2.3.5 循环指令
<view class="item{{ item.completed ? ' completed' :'' }}" wx:for="{{todos }}" wx:key="{{ index }}"bindtap="toggleTodoHandle" data-index="{{ index }}">
<icon class="checkbox" type="{{ item.completed ?'success' : 'circle' }}" size='14'/> <text class="name">{{ item.name }}</text><icon class="remove" type="clear"size="12" catchtap="removeTodoHandle" data-index="{{index }}"/>
</view>
2.3.6 父子组件通信(和vue类似)
第一步:编写子组件
第二步:在子组件的json文件中,将该文件声明为组件{“component”:true}
第三步:在需要引入的父组件的json文件中,声明引入的组件名和路径{“usingComponents”:{“tab-bar”:’../../components/tabBar/tabBar’}}
第四步:父组件向子组件通信,
直接将值赋值给一个变量,在子组件properties中,接收传递的值.
如:父组件 <tab-bar currentpage=”index”></tab-bar>
子组件properties: { currentpage:{ type:String, value:’index’}}
第五步:子组件向父组件通信
//myevent事件名,myEventDetail要传递的参数子组件:
this.triggerEvent(‘myevent’,myEventDetail);
父组件:<bar bind:myevent=”toggleToast”>
2.3.7 路由跳转
wx.navigateTo():将原来的页面保存在页面栈中,只有这样,点击手机返回可以调到上页
wx.redirectTo():先清除栈中的原来页面,然后目标页面进栈
wx.switchTab():先清除栈中的原来页面,然后目标页面进栈, 跳转的页面必须是tabBar中声明的页面
wx.navigateBack(): 只能返回页面栈中指定页面,一般和navigateTo配合使用
2.3.8 钩子函数
onLoad:页面加载资源
onReady:页面初次渲染完成
onShow:页面显示
onHide:页面隐藏
onUnload:页面卸载
onPullDownRefresh:用户下拉动作
onReachBottom:页面上拉触底事件
onShareAppMessage:右上角分享
2.3.9 数据初始化
data: { input: '', todos: [], leftCount: 0, allCompleted: false, logs: [] }访问时,需通过this.data.*来访问
4 效果图
三 VUE+LESS+VUX+WEBPACK3
1 开发环境
主框架VUE以及VUE生态VUE-ROUTER控制路由,UI框架用了移动端开源组件VUX, LESS用于开发样式,是一种预编译的样式。打包用webpack3,和webpack2的区别是配置更简洁清晰,直接使用webpack-dev-server进行构建。
2 项目结构
Build和config是构建项目打包所需的文件,src为真正开发的代码,static为外部静态资源。Src/assets项目所用资源文件,component为可以抽取出来的公共组件,router路由配置,view为视图模块,即单页面应用路由跳转对应的视图。App.vue和main.js为入口文件。
3 主要语法
3.3.1 数据绑定
<input type="text" class="new-todo" v-model="input" placeholder="添加事项">
<span class="name">{{ item.name }}</span>
3.3.2 事件绑定(只需要写函数名即可)
v-on:click 或@click
<span class="btn" @click="toggleAllHandle()">切换选择全部</span>
3.3.3 属性绑定
v-bind:type 或:type
<icon class="checkbox" :type="item.completed ? 'success' : 'circle' " size="14" > </icon>
3.3.4 条件指令
<span v-if="leftCount">{{leftCount}} 事项可选</span>
3.3.5 循环指令
<div :class="item.completed ? 'item completed' : 'item'" v-for="(item,index) in todos" :key="index">
<a @click="toggleTodoHandle(index)"> <icon class="checkbox" :type="item.completed ? 'success' : 'circle' " size="14" ></icon> </a> <span class="name">{{ item.name }}</span> <a @click="removeTodoHandle(index)"> <icon class="remove" type="clear" size="14"></icon>
</a>
</div>
3.3.6 父子组件通信(和vue类似)
第一步:编写子组件
第二步: 在需要使用的父组件中通过import引入,并在components中注册
第三步: 在模板中使用,注意驼峰式转连接符式
第四步:父组件向子组件通信,
父组件向子组件通信,通过属性绑定的方式,在子组件props中,接收传递的值
如:父组件 <tab-bar :currentpage=”index”></tab-bar>
子组件 props: { currentpage:{ type:String, value:’index’}}
第五步:子组件向父组件通信
//myevent事件名,myEventDetail要传递的参数子组件:
子组件:this.$emit(‘myevent’,myEventDetail);
父组件:<bar @myevent=”toggleToast”></bar>
3.3.7 路由跳转
Js代码实现: this.$router.push({path:`/describe/id`, params:{ name:'wl' } })
模板实现: <router-link to="/foo"> go to foo </router-link>
3.3.8 钩子函数
beforeCreate: 组件实例刚被创建,组件属性计算之前,如data属性等
created: 组件实例创建完成,属性已绑定,但dom还未生成,$el属性还不存在
beforeMount: 模板编译/挂载之前
mounted: 模板编译/挂载之后
beforeUpdate: 组件更新之前
updated: 组件更新之后
beforeDestory: 组件销毁前调用
destroyed: 组件销毁后调用
3.3.9 数据初始化
data () { return { input:'', todos:[], leftCount:0, allCompleted:false, logs:[] } } 使用时,直接访问this.input
4 效果图
四 Angular5+Ionic4+SCSS
1 开发环境
Angular和Vue在开发思想上有很多类似的地方,只是从Angular2之后,引入了TypeScript,另外它的依赖注入是Vue没有的。从学习的曲线上讲,这个要相对难一些。要掌握TypeScript需要有很深厚的Es6基础,以及面向对象的思想。 本项目采用Angular4+Ionic4+SCSS,ionic是一个用来开发混合手机应用的,开源的,免费的代码库,利用ionic-cli脚手架直接生成项目结构,项目采用SCSS来开发样式文件。和VUE不同的是,模板,样式,逻辑分别在三个不同的文件中,而VUE的习惯写法是写在同一个文件中,形成单文件的组件或视图。
2 项目结构
Ionic脚手架搭建的项目,src/app是类似vue的app.vue的入口模块。page文件夹放置页面视图,通过ionic generate page **生成,每个视图自动保护.html,.scss,.ts,.module.ts四个文件。分别控制这模板显示,样式布局,业务逻辑以及模块管理。
3 主要语法
4.3.1 数据绑定
<ion-input type="text" placeholder="添加事项" [(ngModel)]="input" (keyup.enter)="addTodoHandle()"></ion-input>
<ion-label>{{item.name}}</ion-label> ody>
4.3.2 事件绑定(只需要写函数名即可)
<ion-label (click)="toggleAllHandle()">切换选择全部</ion-label>
4.3.3 属性绑定
<ion-icon [name]="item.completed ? 'checkmark-circle' : 'radio-button-off'" item-start></ion-icon>
4.3.4 条件指令
<ion-label *ngIf="leftCount">{{leftCount}} 事项可选</ion-label>
4.3.5 循环指令
<ion-item *ngFor="let item of todos,let index=index"> <ion-icon [name]="item.completed ? 'checkmark-circle' : 'radio-button-off'" (click)="toggleTodoHandle(index)" item-start></ion-icon> <ion-label>{{item.name}}</ion-label> <ion-icon name="close-circle" (click)="removeTodoHandle(index)" item-end></ion-icon> </ion-item>
4.3.6 路由跳转
this.router.navigate(['/detail', { id: 'readMore'}])
3.3.8 钩子函数
Angular生命周期钩子
ngOnChanges:检测到输入数据变化,首次触发发生在ngOnInit前。注意对象的属性发生变化时监听不到
ngOnInit:组件初始化,通常会设置一些初始值
ngDoCheck:手动触发更新检查
ngAfterContentInit:内容初始化到组件之后
ngAfterContentChecked:内容变更检测之后
ngAfterViewInit:视图 初始化之后
ngAfterViewChecked:视图发生变化检测之后,这个可以用来保证用户视图的及时更新
ngOnDestroy:组件注销时的清理工作,通常用于移除事件监听,退订可观察对象等
Ionic生命周期钩子
ionViewDidLoad:页面所需资源加载完成触发,但还没有进入这个页面,只会调用一次
ionViewWillEnter:页面即将切换,可以对页面数据进行预处理
ionViewDidEnter:已经进入新页面时触发
ionViewWillLeave:页面准备离开时触发
ionViewDidLeave:页面已经离开时触发,页面处于非激活状态
ionViewWillUnload:页面中的资源即将被销毁时触发
ionViewCanEnter:用于限制是否可以进入某个页面
ionViewCanLeave:用于限制是否可以离开这个页面
3.3.9 数据初始化
通过ts文件的构造函数进行数据初始化。直接通过this访问。
4 效果图
五 koa2+monogodb改造vue版本
1 开发环境
之前的三种实现方法数据的展示和增删都是通过本地存储localStorage实现的。之前自学了monogodb,就想着实验一次,这样从前台到后台就打通了。新建一个node服务项目,服务采用koa2,版本2.2.0,monogodb4.9.5,建了两个数据库表todos和logs。
2 项目结构
项目结构如下所示,app/controllers放置业务逻辑,即接口请求及返回处理;dbhelper里面为数据库的增删改查处理,处理数据库,返回数据库的结果;models为数据库表定义,app.js服务入口。
3 调试接口
开发完成,要测试接口的可用性。利用REST API Testing测试工具,测试接口,增加事项接口:/api/todos/addTodos,测试结果如下:
同理测试todos的查询接口:/api/todos/todos;删除接口:/api/todos/deleteTodos,以及logs的查询接口:/api/logs/logs和增加接口:/api/logs/addLogs。
测试完接口,拿VUE版本的项目做实验,修改项目代码,将原来存储在本地缓存的代码,修改为调用接口,示例如下,因为调用接口不多,就没有用vuex状态管理插件,直接在单文件组件中调用接口,采用的axios,一个基于promise的http库。
本地起项目访问,不采用设置跨域的浏览器的话,会报错的。如下图
于是,利用nginx反向代理,修改本地nginx配置文件。8080端口起的是vue项目,3000端口起的node服务项目,通过本地9090端口访问,就解决了跨域的问题。
同时修改vue项目的开发环境的API_ROOT,通过/apis替换localhost:3000
重新起一下项目,访问一下,啦啦啦,就可以了。
验证一下功能,增加两条事项,然后查看一下操作日志,两条记录。
打开mongodb数据库,核对logs表里面的数据,两条数据,值也对的上。
六 小结
就此,本年度技术总结告一段落,希望2019年完成本职工作的同时,关注最新技术和底层算法,框架是学不完的,框架犹如武功招式,很容易学,难的是修炼内功。招式和内功都得兼备,才能成为武林高手呢。
网友评论