通过new Highway可创建视图实例
const app = new Highway({
$el: $('#app'),
$scope: {
name: 'hello world'
}
});
2.1 属性/方法
- $el: 元素。
- $template:模板字符串。
- $scope:初始化数据。
- $willmount:生命周期函数,编译前调用。不常用
- $mount:生命周期函数,编译完成条用。常用
- didmount:生命周期函数,编译完成调用,在 mount之后。不常用
- $destory:销毁函数,调用销毁当前实例。
- $willunmount:生命周期函数,销毁前调用。不常用
- $unmount:生命周期函数,销毁完成后调用。常用
- didunmount:生命周期函数,销毁完成后调用。在 unmount之后。不常用
<!-- examples/views/prop-function.html -->
<div id="app">
</div>
<script id="template" type="text/template">
<div>i will destory after {{timeout}} seconds</div>
</script>
const app = new Highway({
$el: $('#app'),
$template: $('#template').html(),
$scope: {
timeout: 3
},
$willmount() {
console.log('>>>::$willmount');
},
$mount() {
console.log('>>>::$mount');
this.$interval(() => {
const timeout = this.$scope.$get('timeout') - 1;
if (timeout >= 0) {
this.$scope.$set('timeout', timeout);
} else {
this.$destroy();
}
}, 1000);
},
$didmount() {
console.log('>>>::$didmount');
},
$willunmount() {
console.log('>>>::$willunmount');
},
$unmount() {
console.log('>>>::$unmount');
},
$didunmount() {
console.log('>>>::$didunmount');
},
});
2.2 绑定
2-2-1. 双向绑定
2-2-1-1. 安全
采用{{ property }}或者不指定{{ }}
<!-- examples/views/data-bind.html -->
// html
<p>{{msg}}</p> // '<script>alert(1)'
// js
const app = new Highway({
$el: $('#app'),
$scope: {
msg: '<script>alert(1)'
}
});
2-2-1-2. 非安全
采用{{{ property }}}
<!-- examples/views/data-bind.html -->
<p>{{{msg}}}</p> // '<script>alert(1)'
2-2-2. 单向绑定
模板引擎,编译时根据 scope初始值确定视图,编译完成后无法通过 scope更新,以便节约内存,提高性能
2-2-2-1. 安全
采用[[ property ]]
<!-- examples/views/data-bind.html -->
<p>[[msg]]</p> // '<script>alert(1)'
2-2-2-1. 非安全
采用[[[ property ]]]
<!-- examples/views/data-bind.html -->
<p>[[[msg]]]</p> // '<script>alert(1)'
2.4 作用域
使用$scope作为MVVM框架中的Model
<!-- examples/views/scope.html -->
<div id="app">
<input type="text" hi-value="name"/>
<p>{{name}}</p>
</div>
const app = new Highway({
$el: $('#app'),
$scope: {
name: 'highway'
}
});
2-4-1. $get
使用 scope. get(prop)方法获取属性值,缩写为$get
<!-- examples/views/get.html -->
<div id="app">
<input type="text" hi-value="user.name"/>
<button hi-on:click="showMe">showMe</button>
</div>
const app = new Highway({
$el: $('#app'),
$scope: {
user: {
name: 'highway'
}
},
showMe() {
// equal to this.$scope.$get
alert(this.$get('user.name'));
}
});
如是嵌套属性,可通过属性分割符”.”获取,例如this. scope. get(‘user.name’),$set类同
如是数组属性,可通过[int]数组下标获取,例如this. scope. get(‘students[2].name’),$set类同
2-4-2. $set
使用 scope. set(prop, value)方法获取属性值,缩写为$get
<!-- examples/views/set.html -->
<div id="app">
<input type="text" hi-value="user.name"/>
<button hi-on:click="changeMe">changeMe</button>
</div>
const app = new Highway({
$el: $('#app'),
$scope: {
user: {
name: 'highway'
}
},
changeMe() {
// equal to this.$scope.$set
this.$set('user.name', 'xiage');
}
});
2-4-3. $watch
使用 scope. watch(prop, handler)监控属性变化,缩写为$watch,返回unwather句柄,调用可解除监听
<!-- examples/views/watch.html -->
<div id="app">
<input type="text" hi-value="name"/>
<p>{{name}}</p>
<p>{{logs}}</p>
</div>
const app = new Highway({
$el: $('#app'),
$scope: {
name: 'highway'
},
$mount() {
const unwatcher = this.$watch('name', (newVal, oldVal) => {
this.$set('logs', `value changed, newVal is: ${newVal}, oldVal is: ${oldVal}`);
});
// remove wather
//unwatcher();
}
});
2-4-4. $unwatch
使用 scope. unwatch(prop, [handler])监控属性变化,可缩写为$unwatch,如handler不指定,则移除prop上所有的监听器
<!-- examples/views/unwatch.html -->
<div id="app">
<input type="text" hi-value="name"/>
<p>{{name}}</p>
<p>{{logs}}</p>
<button hi-on:click="unwatch">unwatch</button>
</div>
const app = new Highway({
$el: $('#app'),
$scope: {
name: 'highway'
},
$mount() {
this.$watch('name', (newVal, oldVal) => {
this.$set('logs', `value changed, newVal is: ${newVal}, oldVal is: ${oldVal}`);
});
},
unwatch() {
this.$unwatch('name');
}
});
2-4-5. 常量
单引号或双引号标记的值为常量,并不会从$scope值取值
<!-- examples/views/const.html -->
<div id="app">
<input type="text" hi-value="user.name"/>
<p>{{user.name}}</p>
<p>{{'user.name'}}</p>
<p>{{"user.name"}}</p>
</div>
const app = new Highway({
$el: $('#app'),
$scope: {
user: {
name: 'highway'
}
}
});
2-5. 类定义
可通过Highway.extend抽取为自定义类
<!-- examples/views/klass.html -->
<div id="app-0"></div>
<div id="app-1"></div>
<script id="t-app" type="text/template">
<p>i am {{name}}</p>
</script>
const App = Highway.extend({
$template: $('#t-app').html(),
$scope: {
name: 'highway'
}
});
const app0 = new App({
$el: $('#app-0')
});
const app1 = new App({
$el: $('#app-1')
});