flutter 的初体验
前言:Flutter的官方开发语言为Dart,这个语言也是Google出品的一个语言,即可开发服务端,也可开发app端,还可开发web端。
flutter开发app端,他的性能大大优于H5,并且能够调用硬件资源,如摄像头,由于其拥有热重载和一套代码,可在ios和android手机上,所以在开发成本和效率是高于ios和android开发。
一、框架架构
Flutter Framework
这是一个纯 Dart实现的 SDK,它实现了一套基础库,自底向上,我们来简单介绍一下:
底下两层(Foundation和Animation、Painting、Gestures)在Google的一些视频中被合并为一个dart UI层,对应的是Flutter中的dart:ui包,它是Flutter引擎暴露的底层UI库,提供动画、手势及绘制能力。
Rendering层,这一层是一个抽象的布局层,它依赖于dart UI层,Rendering层会构建一个UI树,当UI树有变化时,会计算出有变化的部分,然后更新UI树,最终将UI树绘制到屏幕上,这个过程类似于React中的虚拟DOM。Rendering层可以说是Flutter UI框架最核心的部分,它除了确定每个UI元素的位置、大小之外还要进行坐标变换、绘制(调用底层dart:ui)。
Widgets层是Flutter提供的的一套基础组件库,在基础组件库之上,Flutter还提供了 Material 和Cupertino两种视觉风格的组件库。而我们Flutter开发的大多数场景,只是和这两层打交道。
Flutter Engine
这是一个纯 C++实现的 SDK,其中包括了 Skia引擎、Dart运行时、文字排版引擎等。在代码调用 dart:ui库时,调用最终会走到Engine层,然后实现真正的绘制逻辑。
二、代码案例
Flutter 模块(注册)
import 'package:flutter/material.dart';
import 'package:fluttertoast/fluttertoast.dart';
import '../../../http/http.dart';
import 'dart:convert';
import "../login/login.dart";
class Register extends StatefulWidget{
@override
_RegisterState createState() => _RegisterState();
}
class _RegisterState extends State<Register>{
//用户名控制器
TextEditingController _unameController = TextEditingController();
//密码控制器
TextEditingController _passwordController = TextEditingController();
@override
Widget build(BuildContext context){
return Scaffold(
appBar: AppBar(
title: Text('注册'),
automaticallyImplyLeading: false,
),
body: Container(
padding: const EdgeInsets.all(30.0),
child:Column(
children: <Widget>[
Container(
margin: const EdgeInsets.only(bottom: 20.0),
child: Text(
'欢迎注册',
style: TextStyle(
fontSize: 30.0,
color: Colors.black54
),
),
),
TextField(
autofocus: true,
controller: _unameController,
decoration: InputDecoration(
labelText: "用户名",
hintText: "您的登录账号",
prefixIcon: Icon(Icons.person)
),
),
TextField(
controller: _passwordController,
decoration: InputDecoration(
labelText: "密码",
hintText: "您的登录密码",
prefixIcon: Icon(Icons.lock)
),
obscureText: true,
),
Container(
margin: const EdgeInsets.all(30.0),
child: SizedBox(
width: double.infinity,
height: 40.0,
child: RaisedButton(
color: Colors.blue,
shape:RoundedRectangleBorder(borderRadius: BorderRadius.circular(5.0)),
child: Text("注册",
style: TextStyle(
color: Colors.white,
fontSize: 15.0
),
),
onPressed: () {
_registerFun();
},
)
)
),
],
),
)
);
}
/*
* 注册
*/
void _registerFun() {
String _userName = _unameController.text;
String _password = _passwordController.text;
if(_userName.length == 0 || _password.length == 0){
Fluttertoast.showToast(
msg: "账号和密码不能为空",
gravity: ToastGravity.CENTER
);
}else{
FocusScope.of(context).unfocus();
var data = {
'username': _userName,
'password': _password
};
postHttp("/api/users/register",data)
.then((response){
final responseJson = json.decode(response.toString());
Map<String, dynamic> newData = responseJson ;
if(newData['code'] == 304){
Fluttertoast.showToast(
msg: "账号已被注册",
gravity: ToastGravity.CENTER
);
}else if(newData['code'] == 200){
Fluttertoast.showToast(
msg: "注册成功",
gravity: ToastGravity.CENTER
);
Navigator.push(context,
MaterialPageRoute(builder: (context) => Login(
userName: _userName,
password: _password
))
);
}
});
}
}
}
涉及到插件模块
- fluttertoast
- dio
node.js 服务端模块(注册)
const dbHelper = require('../db/dbHelper') ;
const xss = require('node-xss').clean;
const jwt= require('jsonwebtoken');
const expressJwt = require('express-jwt');
const hints = require('../config/hints');
const {checkParam} = require('../config/validator-params');
import crypto from 'crypto';
let User = dbHelper.getModel('user');
class UsersClass {
public secret: string;
constructor(){
this.secret = 'dynamic'; //定义签名
}
mdsPassword(password:string){
let md5 = crypto.createHash('md5')
let md5Pwd = md5.update(password).digest('hex')
return md5Pwd;
}
register(req, res, next):void{
let {username, password} = xss(req.body);
checkParam(req,res);
User.findOne({username},(err,doc)=>{
if(err){
res.json(
hints.FINDFAIL({
data: err
})
)
}else if(doc){
res.json(hints.REGISTER_UNAVAILABLE);
}else{
User.create({
username,
password: new UsersClass().mdsPassword(password)
},(error,doc) =>{
res.json(
hints.SUCCESS({
data: {
username: username
},
msg : '注册成功'
})
);
})
}
})
}
login(req, res, next):void{
let {username, password} = xss(req.body);
checkParam(req,res);
User.findOne({username}, (err,doc) =>{
if(err){
res.json(
hints.FINDFAIL({
data: err
})
)
}else if(!doc){
res.json(hints.LOGIN_USER_NOT_EXIST);
}else{
if(new UsersClass().mdsPassword(password) != doc.password){
res.json(
hints.LOGIN_PASSWORD_WRONG
);
}else{
//生成token
const token:String = jwt.sign({
name: username
}, new UsersClass().secret, {
expiresIn: 60000 //秒到期时间
});
res.json(
hints.SUCCESS({
data : {
username: username,
token : token
},
msg : "登录成功"
}
));
}
}
})
}
}
module.exports = {
register: new UsersClass().register,
login: new UsersClass().login
}
涉及到插件模块
- node-xss
- typescript
- express
- express-jwt
- express-validator
- crypto
总结
多看,多写,多思考。
上一篇: Flutter移动应用:按钮输入