update tutorial
This commit is contained in:
parent
9acf8b886a
commit
6d54941a2d
|
@ -155,6 +155,114 @@ const res = mapping({ a: { b: 2, e: [{ f: 3 }, { f: 5 }, { f: 10 }] }, list: lis
|
|||
})
|
||||
```
|
||||
|
||||
### 小程序 MVVM Todo 实战
|
||||
|
||||
定义 TodoItem Model:
|
||||
|
||||
```js
|
||||
let id = 0
|
||||
|
||||
export default class TodoItem {
|
||||
constructor(text, completed) {
|
||||
this.id = id++
|
||||
this.text = text
|
||||
this.completed = completed || false
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
定义 Todo Model:
|
||||
|
||||
```js
|
||||
import TodoItem from './todo-item'
|
||||
import { getAll, add } from './todo-server'
|
||||
|
||||
export default class Todo {
|
||||
constructor() {
|
||||
this.items = []
|
||||
|
||||
this.author = {
|
||||
firstName: 'dnt',
|
||||
lastName: 'zhang'
|
||||
}
|
||||
}
|
||||
|
||||
add(content) {
|
||||
const item = new TodoItem(content)
|
||||
this.items.push(item)
|
||||
add(item)
|
||||
}
|
||||
|
||||
complete(id) {
|
||||
this.items.every(item => {
|
||||
if (id === item.id) {
|
||||
item.completed = true
|
||||
return false
|
||||
}
|
||||
return true
|
||||
})
|
||||
}
|
||||
|
||||
uncomplete(id) {
|
||||
this.items.every(item => {
|
||||
if (id === item.id) {
|
||||
item.completed = false
|
||||
return false
|
||||
}
|
||||
return true
|
||||
})
|
||||
}
|
||||
|
||||
remove(id) {
|
||||
this.items.every((item, index) => {
|
||||
if (id === item.id) {
|
||||
this.items.splice(index, 1)
|
||||
return false
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
定义 ViewModel:
|
||||
|
||||
```js
|
||||
import mapping from '../utils/mapping'
|
||||
import todo from '../model/todo/index'
|
||||
|
||||
class TodoViewModel {
|
||||
constructor() {
|
||||
this.data = {
|
||||
items: []
|
||||
}
|
||||
}
|
||||
|
||||
update() {
|
||||
//一行代码,自动映射!!
|
||||
mapping(todo, this.data)
|
||||
}
|
||||
|
||||
toogleComplete(id) {
|
||||
todo.toogleComplete(id)
|
||||
this.update()
|
||||
}
|
||||
|
||||
add(text) {
|
||||
todo.add(text)
|
||||
this.update()
|
||||
}
|
||||
|
||||
remove(id) {
|
||||
todo.remove(id)
|
||||
this.update()
|
||||
}
|
||||
}
|
||||
|
||||
const vm = new TodoViewModel()
|
||||
|
||||
export default vm
|
||||
```
|
||||
|
||||
说完 mappingjs,来看下 mp-mvvm。你会发现,mp-mvvm 和 omi-mvvm 的 web 模板有很多代码是一模一样的!
|
||||
|
||||
* Model 一模一样
|
||||
|
@ -165,6 +273,94 @@ const res = mapping({ a: { b: 2, e: [{ f: 3 }, { f: 5 }, { f: 10 }] }, list: lis
|
|||
|
||||
> 领域模型复用不变,View 可以移植成任意技术进行渲染
|
||||
|
||||
下面来看下小程序的 View:
|
||||
|
||||
todo-list:
|
||||
|
||||
```html
|
||||
<view>
|
||||
<label class="checkbox {{item.completed&&'completed'}}" wx:for="{{items}}">
|
||||
<view bindtap="checkboxChange" data-id="{{item.id}}">
|
||||
<checkbox checked="{{item.completed}}" />
|
||||
{{item.text}}
|
||||
</view>
|
||||
<image bindtap="remove" data-id="{{item.id}}" src="./remove.png" />
|
||||
</label>
|
||||
</view>
|
||||
```
|
||||
|
||||
```js
|
||||
import vm from '../../view-model/todo'
|
||||
|
||||
Component({
|
||||
properties: {
|
||||
items: {
|
||||
type: Array,
|
||||
value: []
|
||||
}
|
||||
},
|
||||
|
||||
ready: function() {},
|
||||
|
||||
methods: {
|
||||
checkboxChange: function(e) {
|
||||
vm.toogleComplete(e.currentTarget.dataset.id)
|
||||
},
|
||||
remove:function(e){
|
||||
vm.remove(e.currentTarget.dataset.id)
|
||||
}
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
这里把 todo-list 抽象成了一个自定义组件,因为需要有用户输入,所以把 vm 依赖进来,通过 vm 向 model 发指令并且更新视图。在看 todo page:
|
||||
|
||||
```html
|
||||
<view class="container">
|
||||
<view class="title">Hello MVVM</view>
|
||||
<view>
|
||||
<todo-list items="{{items}}" />
|
||||
<view class="form">
|
||||
<input class="input" bindinput="inputHandler" type="text" placeholder="Input your task" value="{{text}}" />
|
||||
<button class="button" bindtap="tapHandler">Add{{items.length+1}}</button>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<other-view />
|
||||
</view>
|
||||
```
|
||||
|
||||
```js
|
||||
import vm from '../../view-model/todo'
|
||||
import create from '../../utils/create'
|
||||
|
||||
create.Page(vm, {
|
||||
onLoad: function() {
|
||||
vm.getAll()
|
||||
},
|
||||
inputHandler: function(e) {
|
||||
this.text = e.detail.value
|
||||
},
|
||||
tapHandler: function() {
|
||||
vm.add(this.text)
|
||||
this.setData({
|
||||
text: ''
|
||||
})
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
需要注意的是,这是使用的是 `create.Page`,并传入了 `vm`,而非以前的 Page。这里需要介绍下两个新的 API:
|
||||
|
||||
* create.Page(vm, options)
|
||||
* create.Component(vm, options)
|
||||
|
||||
那么什么使用使用 create.Page 或者 create.Component,什么时候不需要使用 create,直接使用 Page 和 Component?
|
||||
|
||||
* 如果只需要使用 vm 来发送指令,就不需要 create
|
||||
* 如果你的 vm.data 需要作为视图的 data,请使用 create
|
||||
|
||||
|
||||
|
||||
## License
|
||||
MIT [@dntzhang](https://github.com/dntzhang)
|
||||
|
|
|
@ -2,9 +2,6 @@ import vm from '../../view-model/todo'
|
|||
import create from '../../utils/create'
|
||||
|
||||
create.Page(vm, {
|
||||
data: {
|
||||
text: ''
|
||||
},
|
||||
onLoad: function() {
|
||||
vm.getAll()
|
||||
},
|
||||
|
|
|
@ -15,7 +15,6 @@ create.Page = function (vm, options) {
|
|||
const kv = getArrayPatch(patch.path)
|
||||
patchs[kv.k] = kv.v
|
||||
timeout = setTimeout(() => {
|
||||
console.log(patchs)
|
||||
this.setData(patchs)
|
||||
patchs = {}
|
||||
})
|
||||
|
@ -42,13 +41,11 @@ create.Component = function (vm, options) {
|
|||
|
||||
options.ready = function (e) {
|
||||
vm.data = new JSONProxy(vm.data).observe(false, patch => {
|
||||
console.log(11)
|
||||
clearTimeout(timeout)
|
||||
if (patch.op === 'remove') {//fix arr splice
|
||||
const kv = getArrayPatch(patch.path)
|
||||
patchs[kv.k] = kv.v
|
||||
timeout = setTimeout(() => {
|
||||
console.log(patchs)
|
||||
this.setData(patchs)
|
||||
patchs = {}
|
||||
})
|
||||
|
|
Loading…
Reference in New Issue