Weex入门与进阶指南
版权声明:本文为博主原创文章,未经博主允许不得转载。
原文地址:https://yq.aliyun.com/articles/57554
前言
相比较于React Native的“Learn once, write anywhere”,Weex的口号是“Write once, run everywhere”。考虑到React Native比较任性的向下兼容性,我们也引入了Weex做一番了解。
本文主要分为以下几个部分:
- 构建Hello World程序;
- 集成到现有的iOS工程中;
- 使用Weex的高级特性;
- 如何为Weex做贡献;
一、Weex入门
1.1 Hello Weex
参考官方教程,我们需要先安装Node。在Mac上也可以通过Homebrew直接进行安装:brew install node
。
接着我们需要安装Weex CLI:npm install -g weex-toolkit
,并确保版本号大于0.1.0:
$ weex --version
info 0.3.4
至此,准备工作已经到位,我们可以开始编写Weex程序了。
创建一个名为helloweex.we
的文件,并编写以下代码:
<template>
<div>
<text>Hello Weex</text>
</div>
</template>
通过命令行在helloweex.we
文件所在的目录下执行如下命令:
$ weex helloweex.we
info Fri Jul 08 2016 14:30:31 GMT+0800 (CST)WebSocket is listening on port 8082
info Fri Jul 08 2016 14:30:31 GMT+0800 (CST)http is listening on port 8081
- 1
- 2
- 3
- 1
- 2
- 3
此时,浏览器会打开一个新的标签页展示helloweex.we
的执行效果:
注意到此时地址栏的内容http://127.0.0.1:8081/weex_tmp/h5_render/?hot-reload_controller&page=helloweex.js&loader=xhr
包含着hot reload
字样,所以可以自然联想到当我们在源文件做修改并保存后,该页面会自动刷新展示效果。
1.2 基础结构
上面的示例只是一个非常简单的雏形,而一个比较完整的Weex程序包括三个部分:模板(Template)、样式(Style)和脚本(Script)。
比如我们可以利用上文提到的hot reload
,修改文本的颜色并实时查看效果:
<template>
<div>
<text class="title">Hello Weex</text>
</div>
</template>
<style>
.title { color: red; }
</style>
接着我们添加上第三组成部分:脚本(Script):
<template>
<div>
<text class="title" onclick="onClickTitle">Hello Weex</text>
</div>
</template>
<style>
.title { color: red; }
</style>
<script>
module.exports = {
methods: {
onClickTitle: function (e) {
console.log(e);
alert('title clicked.');
}
}
}
</script>
这样一来,当我们点击文本的时候会出现如下效果:
更多语法相关内容可以参考官方文档。
二、集成到iOS工程
2.1 概述
上面是从前端的角度来初步看Weex的基础效果,对于客户端来讲,这类框架的一个优势就是能够结合Native代码发挥作用。比如在人手紧张的情况下可以一次开发,然后应用在不同平台终端上。
所以,这里讨论下如何将其集成到现有的iOS工程项目当中。
- 参考官方文档,我们先从GitHub下载Weex源码。
- 解压后将目录下的
ios/sdk
复制到现有的iOS工程目录下,并根据相对路径更新既有工程的podfile,然后执行pod update
将Weex iOS SDK集成进既有的iOS项目中; - 在iOS Native代码中初始化Weex SDK,然后创建出要展示Weex程序的ViewController,具体见如下描述;
2.2 在iOS应用上运行Weex程序
在如何集成的文档中,前面说的比较清楚,但是在初始化Weex环境
和渲染Weex实例
这两个小节中,可能是由于代码是从比较大的项目源码中摘录出来的,所以存在一些不必要或没有上下文的代码。
这里描述下在开发调试阶段运行Weex程序。
2.2.1 确定要运行的Weex程序
创建一个WeexDebugViewController
,进行如下布局:
通过填入IP和文件名来定位我们要运行的Weex程序。此外,还可以结合weex helloweex.we --qr -h {ip or hostname}
命令来生成二维码,进行扫描演示,不过解析二维码还是为了获取到Weex程序所在位置。
2.2.2 初始化Weex SDK
开发调试阶段我们可以先将Weex SDK的初始化放在这个WeexDebugViewController
中:
- (void)initWeex {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
[WXAppConfiguration setAppGroup:@"AliApp"];
[WXAppConfiguration setAppName:@"WeexDemo"];
[WXAppConfiguration setAppVersion:@"1.0.0"];
[WXSDKEngine initSDKEnviroment];
[WXLog setLogLevel:WXLogLevelVerbose];
});
}
2.2.3 运行Weex程序的ViewController
点击ShowWeex
按钮时,我们可以根据两个输入框的内容拼接出要运行的Weex程序的位置,然后将其赋值给用来渲染Weex实例的WeexShowcaseViewController
:
- (void)showWeex {
NSString *str = [NSString stringWithFormat:@"http://%@:8081/%@", self.ipField.text, self.filenameField.text];
WeexShowcaseViewController *vc = [WeexShowcaseViewController new];
vc.weexUri = [NSURL URLWithString:str];
[self.navigationController pushViewController:vc animated:YES];
}
接着我们来看看WeexShowcaseViewController
的源码:
#import <WeexSDK/WeexSDK.h>
@interface WeexShowcaseViewController ()
@property (nonatomic, strong) WXSDKInstance *weexSDK;
@end
@implementation WeexShowcaseViewController
- (void)dealloc {
[_weexSDK destroyInstance];
}
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
self.weexSDK.viewController = self;
self.weexSDK.frame = self.view.frame;
[self.weexSDK renderWithURL:self.weexUri];
__weak typeof(self) weakSelf = self;
self.weexSDK.onCreate = ^(UIView *view) {
[weakSelf.view addSubview:view];
};
self.weexSDK.renderFinish = ^(UIView *view) {
;
};
self.weexSDK.onFailed = ^(NSError *error) {
NSLog(@"weexSDK onFailed : %@\n", error);
};
}
- (WXSDKInstance *)weexSDK {
if (!_weexSDK) {
_weexSDK = [WXSDKInstance new];
}
return _weexSDK;
}
2.2.4 运行起来
回到终端上,切换到helloweex.we
文件所在的目录,将Weex的dev server跑起来:
$ weex -s .
info Fri Jul 08 2016 15:38:59 GMT+0800 (CST)http is listening on port 8081
info we file in local path . will be transformer to JS bundle
please access http://30.9.112.173:8081/
然后在Native上填入对应的IP和程序文件名:
到此,将Weex集成到现有iOS工程中算初步告一段落。
三、Weex进阶
当集成工作完成后,会发觉现有功能不足以满足业务需求,所以Weex支持开发者做一些扩展。
3.1 实现Weex接口协议
之前的helloweex.we
示例中只有一个文本元素,现在再添加一个图片元素:
<template>
<div>
<image class="thumbnail" src="http://image.coolapk.com/apk_logo/2015/0817/257251_1439790718_385.png"></image>
<text class="title" onclick="onClickTitle">Hello Weex</text>
</div>
</template>
<style>
.title { color: red; }
.thumbnail { width: 100; height: 100; }
</style>
<script>
module.exports = {
methods: {
onClickTitle: function (e) {
console.log(e);
alert('title clicked.');
}
}
}
</script>
然后再执行:$ weex helloweex.we
来运行查看效果:
可以在浏览器里看到这次多了一张图片。但是如果是运行在Native端,图片则得不到展示:
这是由于Weex SDK没有提供图片下载能力,需要我们来实现。
3.2 实现图片下载协议WXImgLoaderProtocol
这个基本可以参考官方文档来实现。
3.2.1 定义图片下载Handler
#import <WeexSDK/WeexSDK.h>
@interface WeexImageDownloader : NSObject <WXImgLoaderProtocol>
@end
3.2.2 实现协议接口
这个类必须遵循WXImgLoaderProtocol
协议,并实现该协议定义的接口:
#import "WeexImageDownloader.h"
#import <SDWebImage/SDWebImageManager.h>
@implementation WeexImageDownloader
- (id<WXImageOperationProtocol>)downloadImageWithURL:(NSString *)url
imageFrame:(CGRect)imageFrame
userInfo:(NSDictionary *)options
completed:(void(^)(UIImage *image, NSError *error, BOOL finished))completedBlock {
return (id<WXImageOperationProtocol>)[[SDWebImageManager sharedManager] downloadImageWithURL:[NSURL URLWithString:url] options:0 progress:^(NSInteger receivedSize, NSInteger expectedSize) {
} completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) {
if (completedBlock) {
completedBlock(image, error, finished);
}
}];
}
@end
3.2.3 注册Handler
[WXSDKEngine registerHandler:[WeexImageDownloader new] withProtocol:@protocol(WXImgLoaderProtocol)];
这样一来,再次运行程序就可以看到图片了:
这样设计的好处主要是考虑了不同App依赖的网络库或者图片下载缓存库不同,避免Weex强依赖于一些第三方库,遵循依赖抽象而不是具体的原则。
BTW,我个人感觉Weex
缩写成WX
,WeexImageLoaderProtocol
缩写成WXImgLoaderProtocol
,不是很好看。
3.2 自定义UI组件
如果Weex的内置标签不足以满足要求时,我们可以自定义Native组件,然后暴露给.we文件使用。
比如我们可以定义一个WeexButton
,继承自WXComponent
,然后将其注册进Weex SDK:
[WXSDKEngine registerComponent:@"weex-button" withClass:[WeexButton class]];
这样一来,我们就可以在.we文件中使用这个标签了:
<weex-button class="button" title="hello"></weex-button>
标签中的属性我们可以在初始化函数中获得:
- (instancetype)initWithRef:(NSString *)ref
type:(NSString*)type
styles:(nullable NSDictionary *)styles
attributes:(nullable NSDictionary *)attributes
events:(nullable NSArray *)events
weexInstance:(WXSDKInstance *)weexInstance {
self = [super initWithRef:ref type:type styles:styles attributes:attributes events:events weexInstance:weexInstance];
if (self) {
_title = [WXConvert NSString:attributes[@"title"]];
}
return self;
}
通过这些属性,我们可以在组件生命周期中修改组件的样式,比如设置按钮的title:
- (void)viewDidLoad {
[super viewDidLoad];
self.innerButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
self.innerButton.frame = self.view.bounds;
[self.view addSubview:self.innerButton];
[self.innerButton setTitle:self.title forState:UIControlStateNormal];
[self.innerButton addTarget:self action:@selector(onButtonClick:) forControlEvents:UIControlEventTouchUpInside];
}
3.3 自定义模块
除了UI组件之外,有些时候我们希望JS层面能够调用Native的一些功能,比如通过JS代码让Native打开一个特定的ViewController。这时候,我们可以自定义一个模块向JS层面暴露API:
@synthesize weexInstance;
WX_EXPORT_METHOD(@selector(call:withParam:callback:))
- (void)call:(NSString *)api withParam:(NSDictionary *)param callback:(WXModuleCallback)callback {
- 1
- 2
- 3
- 4
- 1
- 2
- 3
- 4
注意点如下:
1. 需要遵循WXModuleProtocol
协议;
2. 需要合成(synthesize
)weexInstance
属性;
3. 使用WX_EXPORT_METHOD
来暴露API;
4. 使用WXModuleCallback
进行回调;
完成以上编码后,向Weex SDK注册:[WXSDKEngine registerModule:
,就可以在.we文件中使用了:
<script>
module.exports = {
methods: {
onClickTitle: function (e) {
var mymodule = require('@weex-module/mymodule');
mymodule.call('api', {}, function(ret) {
});
}
}
}
</script>
四、为Weex做贡献
由于Weex刚开源不久,如果开发者发现一些问题或者需要改善的地方,可以直接在GitHub上进行fork,修改完后提交Pull Request。
前端开发-Weex初试
1 Weex介绍
weex是阿里2016年开源的一套跨移动端(Andriod/IOS/Wap)的前端框架,采用VUE,较React Native入门相对简单
2 Weex安装与初始化
2.1 安装NodeJS和NPM
略过,默认安装了
注意:nodejs的版本须大于4.5.0
2.2 安装weex
- npm install -g week-toolkit,全局安装week工具集合
- 安装完成后命令行输入weex,查看是否有命令帮助内容,如果提示没有weex命令,表示weex没有安装好,检查一下nodejs的版本
2.3 初始化一个项目
- 新建一个项目目录
- 命令行输入 weex init,这时会自动下载和生成相关文件
- 运行npm install,安装相关依赖包
2.4 与IDE集成
我使用的是WebStrom
- 将刚才新建的工程导入webstrom中
- 在setting->plugins中安装weex的插件:weex、weex langugge support,用于创建we文件和支持weex语法(VUE)
- 直接在webstrom的终端中运行weex相关命令
2.5 相关命令
- weex ***.we : 运行调试xxx页面,支持热加载,默认端口是8081和8082 8082是热加载端口
- npm run build : build 在package.json定义的脚本命令,执行webpack
- npm run dev : dev 在package.json定义的脚本命令,执行webpack --watch
- npm run serve : serve package.json定义的脚本命令,启动serve服务
- weex xxx.we --qr: 运行调试xxx页面,并依据地址url生成二维码,主要是在iOS和Android上查看效果,设备须在同一个局域网中
webpack和serve的依赖包需要安装
3 第一个Weex项目
3.1 主页面
3.1.1 main.we
<template>
<scroller>
<text>用户名:</text>
<input id="top" type="text" autofocus="true" placeholder="请输入用户名" value="{{username}}" oninput="usernameoninput" style="margin-top: 200px;margin-left: 200px;font-size:32px;">
</input>
<text>密码:</text>
<input type="password" autofocus="true" placeholder="请输入密码" value="{{password}}" oninput="passwordoninput" style="margin-top: 200px;margin-left: 200px;font-size:32px;">
</input>
<input type="success" value="登录" onclick="login" style="margin-top: 200px;margin-left: 200px;">
</input>
</scroller>
</template>
<style>
</style>
<script>
var common = require('./lib/common.js');
module.exports = {
data: {
root:"dist",
username:"",
password:""
},
ready: function () {
},
methods:{
login:function(e){
var storage = require('@weex-module/storage');
var self = this;
var bundleUrl = this.$getConfig().bundleUrl;
var url = common.getUrl(bundleUrl,'mainindex.lib','dist');
storage.setItem('username', self.username, function(e) {
self.$openURL(url)
});
},
usernameoninput:function(e){
this.username = e.value;
},
passwordoninput:function(e){
this.password = e.value;
}
}
}
</script>
3.1.2 内置组件使用
3.1.2.1 数据存储与读取
var storage = require('@weex-module/storage');//引入存储
storage.setItem('username', self.username, function(e) {//将用户名存进客户端,对应的key是usernam
});
var storage = require('@weex-module/storage');
var self = this;
storage.getItem("username",function(e){//读取数据
self.headinfo = e.data;
});
3.1.2.2 数据请求
var stream = require('@weex-module/stream');
stream.fetch({
method: 'GET',
url: "http://192.168.169.124:3000/testhttpget.do",
type:'json'
}, function(response) {
self.body = response.data.info;
},function(response){
});
其他内置组件使用,请参看API
3.2 自定义组件
3.2.1 新建we文件
<template>
<div class="headclass">
<text>{{headinfo}}</text>
</div>
</template>
<script>
module.exports = {
data:{
headinfo:"welcome to this"
},
ready:function(){
var storage = require('@weex-module/storage');
var self = this;
storage.getItem("username",function(e){
self.headinfo = e.data;
});
}
}
</script>
<style>
.headclass{
margin-top: 200px;
}
</style>
3.2.2 引入
<script>
require('./components/headdiv.we')
module.exports = {
data:{
}
}
</script>
3.2.3 使用
<template>
<div class="bg">
<headdiv></headdiv>
</div>
</template>
3.3 引用JS文件与打包
3.3.1 定义JS
var getUrl = function(bundleUrl,fileName,dir,host){
var nativeBase;
var isAndroidAssets = bundleUrl.indexOf('file://assets/') >= 0;
var isiOSAssets = bundleUrl.indexOf('file:///') >= 0 && bundleUrl.indexOf('WeexDemo.app') > 0;
if (isAndroidAssets) {
nativeBase = 'file://assets/';
}
else if (isiOSAssets) {
nativeBase = bundleUrl.substring(0, bundleUrl.lastIndexOf('/') + 1);
}
else {
host = host||'localhost:8080';
var matches = /\/\/([^\/]+?)\//.exec(bundleUrl);
if (matches && matches.length >= 2) {
host = matches[1];
}
nativeBase = 'http://' + host + '/' + dir + '/';
}
var h5Base = './index.html?page=./' + dir + '/';
// in Native
var base = nativeBase;
if (typeof window === 'object') {
base = h5Base;
}
return base+fileName;
}
3.3.2 引用
var common = require('./lib/common.js');
打包
require('webpack')
require('weex-loader')
var path = require('path')
module.exports = {
entry: {//主we页面
main: path.join(__dirname, 'src', 'main.we?entry=true')
},
output: {
path: 'dist',
filename: '[name].lib'
},
module: {
loaders: [
{
test: /\.we(\?[^?]+)?$/,
loaders: ['weex-loader']
},
{
test: /\.js$/,
loaders: ['weex-loader'] //将js文件打包
}
]
}}
3.4 页面跳转
self.$openURL(url)
须要注意Android和iOS的跳转,要提前定义好相关协议
4 与Android的集成
4.1 创建工程
创建Android 工程
4.2 引入weex
- 下载源码 git clone https://github.com/alibaba/weex
- File->New-Import Module->选择WEEX SDK Module(weex/android/sdk)->Finish
- app 的build.gradle 中添加如下依赖:compile project(':weex_sdk')
4.3 引入相关组件
apply plugin: 'com.android.application'
android {
compileSdkVersion 24
buildToolsVersion "25.0.0"
defaultConfig {
applicationId "demo.android.weex.tomsnail.cn.weexandroiddemo"
minSdkVersion 21
targetSdkVersion 24
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
exclude group: 'com.android.support', module: 'support-annotations'
})
compile 'com.android.support:appcompat-v7:24.2.1'
compile 'com.android.support:design:24.2.1'
compile 'com.taobao.android:dexposed:0.1.8'
compile 'com.loopj.android:android-async-http:1.4.9@aar'
compile 'com.facebook.fresco:fresco:0.12.0+'
compile 'com.facebook.fresco:animated-gif:0.12.0'
compile 'com.squareup.okhttp:okhttp:2.3.0'
compile 'com.squareup.okhttp:okhttp-ws:2.3.0'
compile 'com.squareup.okio:okio:1.0.1'
compile 'com.alibaba:fastjson:1.1.46.android'
compile 'com.android.support:support-annotations:23.2.1'
compile 'com.jakewharton.scalpel:scalpel:1.1.2'
compile 'com.squareup.picasso:picasso:2.5.2'
//compile 'com.google.android.gms:play-services-appindexing:8.1.0'
compile 'com.taobao.android:weex_inspector:0.0.8.1'
compile project(':weex_sdk')
testCompile 'junit:junit:4.12'
compile 'com.google.android.gms:play-services-appindexing:8.4.0'
}
4.4 创建基础类
- WXApplication
- ImageAdapter
- MainActivity
4.5 配置AndroidManifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="demo.android.weex.tomsnail.cn.weexandroiddemo">
<!-- To auto-complete the email text field in the login form with the user's emails -->
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.READ_PROFILE" />
<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission
android:name="android.permission.WRITE_EXTERNAL_STORAGE">
</uses-permission>
<application
android:name=".WXApplication"
android:allowBackup="false"
android:icon="@mipmap/ic_launcher"
android:label="weexandroiddemo"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".Main1Activity">
</activity>
<!-- ATTENTION: This was auto-generated to add Google Play services to your project for
App Indexing. See https://g.co/AppIndexing/AndroidStudio for more information. -->
<meta-data
android:name="com.google.android.gms.version"
android:value="@integer/google_play_services_version" />
</application>
</manifest>
4.6 加入js
在src下新建assets文件夹,将weex生成的dist下的文件放入以便加载 WXFileUtils.loadAsset(path, context)
4.7 运行
连接设备运行app,建议使用真机,使用模拟机占用电脑资源较多
5 相关问题
5.1 升级
- 依据版本号规划进行升级
- 打包下载,本地解压存储、文件缓冲
5.2 自定义事件
- 定义好相关协议
- SPA化
5.3 消息与推送
- 只做Native功能
5.4 Native功能
- 比如拍照上传、相册等功能还是需要移动端开发人员开发和集成
5.5 持续集成
- 重新定义集成流程,将weex的发布与移动端的发布联合定义
相关代码在整理后近期放在github上
Weex入门与进阶指南的更多相关文章
- Java 服务端入门和进阶指南
作者:谢龙 链接:https://www.zhihu.com/question/29581524/answer/44872235 来源:知乎 著作权归作者所有,转载请联系作者获得授权. 现在互联网上资 ...
- Python语言学习之Python入门到进阶
人们常说Python语言简单,编写简单程序时好像也确实如此.但实际上Python绝不简单,它也是一种很复杂的语言,其功能特征非常丰富,能支持多种编程风格,在几乎所有方面都能深度定制.要想用好Pytho ...
- 服务端工程师入门与进阶 Java 版
前言 欢迎加入我们.这是一份针对实习生/毕业生的服务端开发入门与进阶指南.遇到问题及时问你的 mentor 或者直接问我. 建议: 尽量用google查找技术资料. 有问题在stackoverflow ...
- Wireshark入门与进阶系列(二)
摘自http://blog.csdn.net/howeverpf/article/details/40743705 Wireshark入门与进阶系列(二) “君子生非异也,善假于物也”---荀子 本文 ...
- 可怕!字节跳动大牛爆出的“Android进阶指南”,强到无法形容,GitHub已标星“8.5k”!
前言 从去年8月份开始,我开始重新找工作,在这期间刷了不少面试题和大牛博客,无意中薅到一份字节跳动大牛整理的一份"Android进阶指南",包含Android面试常见问题.主流技术 ...
- 推荐 10 本 Go 经典书籍,从入门到进阶(含下载方式)
书单一共包含 10 本书,分为入门 5 本,进阶 5 本.我读过其中 7 本,另外 3 本虽然没读过,但也是网上推荐比较多的. 虽然分了入门和进阶,但是很多书中这两部分内容是都包含了的.大家看的时候可 ...
- HTML5游戏开发进阶指南(亚马逊5星畅销书,教你用HTML5和JavaScript构建游戏!)
HTML5游戏开发进阶指南(亚马逊星畅销书,教你用HTML5和JavaScript构建游戏!) [印]香卡(Shankar,A.R.)著 谢光磊译 ISBN 978-7-121-21226-0 201 ...
- 【读书笔记】读《高性能网站建设指南》及《高性能网站建设进阶指南:Web开发者性能优化最佳实践》
这两本书就一块儿搞了,大多数已经理解,简单做个标记.主要对自己不太了解的地方,做一些记录. 一.读<高性能网站建设指南> 0> 黄金性能法则:只有10%~20%的最终用户响应时间 ...
- SQL Server 扩展事件(Extented Events)从入门到进阶(1)——从SQL Trace到Extented Events
由于工作需要,决定深入研究SQL Server的扩展事件(Extended Events/xEvents),经过资料搜索,发现国外大牛的系列文章,作为“学习”阶段,我先翻译这系列文章,后续在工作中的心 ...
随机推荐
- 《JDK 8.0 学习笔记》1~3章
第一章 Java平台概论 了解Java的发展历程和相关术语如JDK.JVM.JRE等 第二章 从JDK到IDE 书本介绍了新建Java程序的注意事项以及在cmd和Eclipse环境下如何运行Java, ...
- Java基础学习笔记(一)
Java基础学习笔记(一) Hello World 基础代码学习 代码编写基础结构 class :类,一个类即一个java代码,形成一个class文件,写于每个代码的前端(注意无大写字母) XxxYy ...
- FromBottomToTop团队项目总结
FromBottomToTop团队项目总结 项目实现情况 关于塔防游戏项目,已实现下列内容 - 游戏设有菜单,附有简介与游戏玩法 - 游戏设有不同的场景地图可供玩家选择 - 通过智能算法,计算小怪的路 ...
- ssh-copy-id使用非默认22端口
ssh-copy-id使用及非默认22端口时报错 ssh-copy-id使用介绍 说明:ssh-copy-id命令可以把本地的ssh公钥文件安装到远程主机对应的账户下. 功能:ssh-copy-id ...
- Redis之Python 使用 Redis
Python 使用 Redis 参考文档: http://redis.cn/clients.html#python https://github.com/andymccurdy/redis-py 安装 ...
- "CMAKE_CXX_COMPILER-NOTFOUND"
CMake Error: your CXX compiler: "CMAKE_CXX_COMPILER-NOTFOUND" was not found. Please set CM ...
- undefined 与 null
typeof null - 'object typeof undefined - 'undefined' Boolean(null) - false Boolean(undefin ...
- domain---Node.js 异步异常的处理与domain模块解析
var domain = require('domain'); app.use(function (req, res, next) { var reqDomain = domain.create(); ...
- hdu4565矩阵快速幂
这题太坑了...刚开始以为可以用|a+sqrt(b) 1|水过...结果tle,还一直想明明我logn的做法怎么可能tle.. | 0 1| 实在无奈看的题解 (a+sqr ...
- HDU1698 线段树入门之区间修改/查询(lazy标记法)
Just a Hook Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total ...