网址:https://github.com/maichong/labrador
之前一直用的微信开发者工具去直接修改代码,倒不是说这样不行,就是不太友好,目录结构混乱,逻辑不清晰,身为开发者,我有时候都会混淆一些东西,更何况团队开发,
所以不建议使用微信开发工具去直接修改代码,今天在网上看见一个Labrador框架,所以准备研究一下,正式学习之前需要具备一些知识 redux,
首先系统中需要nodejs和npm,然后全局安装Labrador-cli
npm install -g labrador-cli
labrador create demo //新建一个项目
cd demo //进入demo
在IDE中编辑src目录下的源码,然后再项目根目录中运行labrador build命令构建项目,然后在微信开发者工具中调试界面中点击左侧菜单的 重启 按钮 ,即可查看效果
labrador create <name> //创建项目
labrador build 【opation】 //构建当前项目
labrador watch 【opation】 //编辑当前项目并检测文件改动
labrador generate 【opation】 <type> <name>
//创建新组建,页面,redux saga
+ labrador generate page home/home //创建文件夹和新的页面
+ labrador generate component home //创建home组件
+ labrador generate redux home //创建redux文件
+ labrador generate saga home //创建saga文件
wxml中支持import和include,但仅时视图模板中可用,并非组件可重用,
wxml其实基于可重用组件,但不允许自定义组件
重要的是,只有真正用到的js文件才被labrador命令加入到项目目录中。这样一个小小的改进象征着我们的小程序可以便捷调用NPM仓库中海量的扩展库!
源码中const _ = require('lodash'); 被编译为 var _ = require('./npm/lodash/lodash.js');
commonents文件夹中存放公用的组件
在 src/pages/index/index.less 中加入代码 @import ‘list’ 即可调用list组件的样式,如果在src/components/list中找不到list.less,那么编译命令将在NPM包中寻找 node_modules/list/index.less 。
在 src/pages/index/index.xml 中加入代码 即可调用list组件的模板文件,component 是Labrador自定义的组件,编译后对应生成 import 和 template。如果在src/components/list中找不到list.xml,那么编译命令将在NPM包中寻找 node_modules/list/index.xml
默认首页的示例代码
index.js
import wx, { Component } from 'labrador';
import List from '../../components/list/list';
import Title from '../../components/title/title';
import Counter from '../../components/counter/counter';
export default class Index extends wx.Component {
state = {
userInfo: {},
mottoTitle: 'Hello World',
count: 0
};
children() {
return {
list: {
component: List
},
motto: {
component: Title,
props: {
text: this.state.mottoTitle
}
},
counter: {
component: Counter,
props: {
count: this.state.count,
onChange: this.handleCountChange
}
}
};
}
handleCountChange(count) {
this.setState({ count });
}
//事件处理函数
handleViewTap() {
wx.navigateTo({
url: '../logs/logs'
});
}
async onLoad() {
try {
//调用应用实例的方法获取全局数据
let userInfo = await wx.app.getUserInfo();
//更新数据
this.setState({ userInfo });
this.update();
} catch (error) {
console.error(error.stack);
}
}
onReady() {
this.setState('mottoTitle', 'Labrador');
}
}
js中export default会导出一个默认的类,不可手动调用Page(),因为在编译之后pages目录下所有的js全会自动调用Page()方法声明页面。
children()方法返回该组件依赖,包含的其他自定义组件,
以上的代码中包含了三个自定义组件list ,title,counter
children()方法包含两个属性,component属性定义了组件类,props属性定义了父组件向子组件传递的props属性对象,
注意所有的组件生命周期都支持async,但默认的是普通函数,如果函数内没有异步操作,建议采用普通函数,async函数会有一定的性能开销,可能无法顺畅的执行
<view class="container">
<view class="userinfo" catchtap="handleViewTap">
<image class="userinfo-avatar" src="{{ state.userInfo.avatarUrl }}" background-size="cover"/>
<text class="userinfo-nickname">{{ state.userInfo.nickName }}</text>
</view>
<view class="usermotto">
<component key="motto" name="title"/>
</view>
<component key="list"/>
<component key="counter"/>
</view>
以上这段代码中使用了labrador提供的 标签,此标签的作用是导入一个自定义组件的布局文件。标签有两个属性,分别是key(必须)和name(可选,默认是key的值)。key与js逻辑代码中的组件key对应,name是 组件的目录名。
labrador支持多层组件嵌套
逻辑 src/components/list/list.js
import wx, { Component } from 'labrador';
import Title from '../title/title';
import Item from '../item/item';
import { sleep } from '../../utils/util';
export default class List extends Component {
constructor(props){
super(props);
this.state = {
items: [
{ id:1, title: 'Labrador' },
{ id:2, title: 'Alaska' }
]
};
}
children (){
return {
title:{
component: Title,
props: { text: 'The List Title' }
},
listItems: this.state.items.map((item) => {
return {
component: Item,
key: item.id,
props: {
item: item,
title: item.title,
isNew: item.isNew,
onChange: (title) => { this.handleChange(item, title) }
}
};
})
};
}
async onLoad() {
await sleep(1000);
this.setState({
items: [{ id:3, title: 'Collie', isNew: true }].concat(this.data.items)
});
}
handleChange(item, title) {
let items = this.state.items.map((i) => {
if(item.id == i.id){
return Object.assign({},i,{ title });
}
return i;
});
this.setState({ items });
}
}
以上代码中children()返回的listItem子组件定义时,是一个组件数组,数组的每一项都是一个子组件的定义,并且需要每一项的key属性,key属性将用于模板渲染性能优化,建议将唯一且不宜变化的值设为子组件的key