MVVM、MVC各有优缺点吧,当时angular火爆的时候我就曾学习过,但是项目当中一直没敢试用,一是、团队成员对angular都不了解,需要重新学习,二、项目研发周期比较短 三、angular太重,因此放弃了angular。作为一名开发者,项目选型问题非常重要,不能说为了学习研究技术我就用新技术,不是说排斥新技术,个人也是一个新技术爱好者,只不过很多项目的选型要根据实际情况来,没有好与坏,只有适合不适合。当然、现在vue这么精干,还是值得一试,打算下一个项目用vue来写,好好学习一下。
一、hello word 废话不多说,来个代码研究一下,看了vue的文档,发现文档太友好了,不愧是国人开发的产品,文档就是不一样哈哈,点一个赞。
简单些了一下demo
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<!DOCTYPE html>
<html >
<head >
<meta charset ="utf-8" />
<meta http-equiv ="X-UA-Compatible" content ="IE=edge" />
<title > 前端观察</title >
<meta name ="description" content ="专注于网站前端设计与开发" />
<meta name ="HandheldFriendly" content ="True" />
<meta name ="viewport" content ="width=device-width, initial-scale=1.0" />
<meta name ="MobileOptimized" content ="320" >
</head >
<body >
<div id ="test-container" >
Hello {{msg}}
</div >
<script type ="text/javascript" src ="vue.js" > </script >
<script >
new Vue({
el:'#test-container' ,
data:{
msg:'Great Boy'
}
})
</script >
</body >
</html >
显示效果点击查看
非常简洁,简直就是一个模板引擎在渲染的感觉,不过有一个问题就是由于是后加载的vue.js,因此渲染的时候会出现Hello ,原来是由于页面渲染的时候vue还没加载呢。所以我们把vue放到head里加载,就不会有这个问题了。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<!DOCTYPE html>
<html >
<head >
<meta charset ="utf-8" />
<meta http-equiv ="X-UA-Compatible" content ="IE=edge" />
<title > 前端观察</title >
<meta name ="description" content ="专注于网站前端设计与开发" />
<meta name ="HandheldFriendly" content ="True" />
<meta name ="viewport" content ="width=device-width, initial-scale=1.0" />
<meta name ="MobileOptimized" content ="320" >
<script type ="text/javascript" src ="vue.js" > </script >
</head >
<body >
<div id ="test-container" >
Hello {{msg}}
</div >
<script >
new Vue({
el: '#test-container' ,
data: {
msg:'Great Boy'
}
})
</script >
</body >
</html >
点击查看 hello word就这么简单了,所以说vue其实是基于viewModel的,也就是数据加业务的显示。
二、双向绑定 这个可以说是angular的特性,vue也参考了angular等一些特性,这个非常有用,可以省去了很多dom操作,也是我非常敢兴趣的一个地方,还有非常感兴趣的一个地方就是组件,目前的项目我一直采取fis来构建,还是特别喜欢他的widget,也类似与组件的封装。可以把css html js封装成一个组件文件夹。非常好维护,这点fis做的很不错,推荐哈。先看来个demo代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<!DOCTYPE html>
<html >
<head >
<meta charset ="utf-8" />
<meta http-equiv ="X-UA-Compatible" content ="IE=edge" />
<title > 前端观察</title >
<meta name ="description" content ="专注于网站前端设计与开发" />
<meta name ="HandheldFriendly" content ="True" />
<meta name ="viewport" content ="width=device-width, initial-scale=1.0" />
<meta name ="MobileOptimized" content ="320" >
<script type ="text/javascript" src ="vue.js" > </script >
</head >
<body >
<div id ="test-container" >
Hello {{msg}}
<input v-model ="msg" />
</div >
<script >
new Vue({
el:'#test-container' ,
data:{
msg:'Great Boy'
}
})
</script >
</body >
</html >
语法很简单,欣赏中….点击查看demo
二、渲染列表 看了下api很简单,直接用v-for搞定,我相信开发过程序目前大脑一定很多想法,我脑中闪过,如何 分页、ajax怎么写???后续在学习吧 代码以及查看demo
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
<!DOCTYPE html>
<html >
<head >
<meta charset ="utf-8" />
<meta http-equiv ="X-UA-Compatible" content ="IE=edge" />
<title > 前端观察</title >
<meta name ="description" content ="专注于网站前端设计与开发" />
<meta name ="HandheldFriendly" content ="True" />
<meta name ="viewport" content ="width=device-width, initial-scale=1.0" />
<meta name ="MobileOptimized" content ="320" >
<script type ="text/javascript" src ="vue.js" > </script >
</head >
<body >
<div id ="test-container" v-on:click ="clickTest" >
<div >
Hello {{msg}}
</div >
<div >
<div v-for ="item in list" >
{{item.name}}
</div >
</div >
</div >
<script >
var data = {
msg:'Great Boy' ,
list: [{
name:'张三'
},{
name:'李四'
},{
name:'王五'
}]
}
var test = new Vue({
el:'#test-container' ,
data:data,
methods: {
clickTest: function (e ) {
console .dir(e);
data.push(data.list.push({'name' :'周六' }));
}
}
});
</script >
</body >
</html >
看到这分页我就知道如何写拉,只需要把data里面的数据替换就好了,如果是下拉加载的话,可以直接拼接data数据,但是不知道会不会影响滚动条的位置,这个只有试试了.
其实我觉得vue给我感觉最好的一部分就是解放了dom操作,我们只需要操作数据,数据就会驱动dom,我相信大部分程序员都是自由主义这,我们可以把vue看成是vm,
也及时dom的渲染和事件的监听,这样自己的业务逻辑可以根据需求自行设置,我不提倡那种写好的框架,业务逻辑能否写好,框架是很难做到的,因为需求不同,需要不同的设计方式.
三、指令与事件 指令就是特殊的带有前缀 v-的,例如v-if v-for v-on v-bind
1 v-if v-show v-if 就是 if else的逻辑判断,例如,目前貌似没有看到支持elseif的指令,不知道是什么原因1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<h3 > v-if例子</h3 >
<div id ="if-demo" >
<p v-if ="hello" > 是</p >
<p v-else > 否<p >
<p v-if ="test1 == 1" > 1</p >
<p v-else > 3</p >
<p v-show ="test1 == 1" > 1</p >
</div >
<script >
new Vue({
el:'#if-demo' ,
data:{
hello: true ,
test1:'1' ,
test2:'2'
}
})
</script >
还有一个指令v-show,跟v-if类似,但是v-show是通过display去控制,类似与jquery的show
2 v-for v-for 就是遍历指令1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<div id ="for-demo" >
<ul v-for ="item in list" >
<li >
<div > 书名:{{item.title}}</div >
<div > 价格:{{item.price}}</div >
</li >
</ul >
</div >
<script >
new Vue({
el:'#for-demo' ,
data:{
list:[{
title:'javascript设计模式' ,
price: 12
},{
title:'javascript高级开发' ,
price: 20
},{
title:'javascript算法与数据结构' ,
price: 40
},{
title:'javascript王者归来' ,
price: 100
}]
}
})
</script >
3 v-on 和 v-bind v-on 指令用于监听DOM事件1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
v-bind 指令用于响应地更新 HTML 特性
例如<a v-bind:href ="url" > </a > 最终生成 `<a href ="http://www.baidu.com" > </a > `
例如<img v-bind:src ="url" /> 最终生成 `<img src ="http://www.baidu.com" /> `
<div id ="bind-demo" >
<a v-bind:href ="url" > v-bind href</a >
<a v-bind:test ="url" > v-bind test</a >
<div v-on:click ="clickTest" > v-on绑定</div >
</div >
<script >
new Vue({
el:'#bind-demo' ,
data:{
url:'http://www.baidu.com' ,
},
methods:{
clickTest: function ( ) {
alert('点击测试' )
}
}
})
</script >
1
2
3
4
5
6
7
8
9
10
11
12
<a v-on:click.stop ="doThis" > </a >
<form v-on:submit.prevent ="onSubmit" > </form >
<a v-on:click.stop.prevent ="doThat" >
<form v-on:submit.prevent > </form >
v-bind还可以绑定多个,如我们常用的class,目前vue支持多种方式,
支持这种的class=""
写法和v-bind:class
,但是官方文档说明,希望只支持一种写法,不要混用
1)v-bind: class可以支持与普通class共存1
2
3
4
5
6
<div class ="static" v-bind:class ="{ 'class-a': isA, 'class-b': isB }" > </div >
data: {
isA: true,
isB: false
}
渲染为
1
2
<div class ="static class-a" > </div >
当 isA 和 isB 变化时,会更新class的值,例如都未true时,渲染为
1
2
><div class ="static class-a class-b" > </div >
2)v-bind:class数组写法
1
2
3
4
5
6
<div v-bind:class ="[classA, classB]" >
data: {
classA: 'class-a',
classB: 'class-b'
}
渲染为1
2
<div class ="class-a class-b" > </div >
3)三元表达式写法
1
2
<div v-bind:class ="[classA, isB ? classB : '']" >
当isB为ture时,渲染为
1
2
<div class ="classA classB" > </div >
4) 1.0.19+支持对象写法
1
2
<div v-bind:class ="[classA, { classB: isB, classC: isC }]" >
5) 内联写法
1
2
3
4
5
6
<div v-bind:style ="{ color: activeColor, fontSize: fontSize + 'px' }" > </div >
data: {
activeColor: 'red',
fontSize: 30
}
渲染为
1
2
<div style ="color: red,fontSize:30px;" > </div >
自定义指令 除了内置的指令, vue允许自己定义指令,例如Vue.directive(id, definition)
可以注册一个全局的指令,接收两个参数指令id和定义的对象. 定义的对象可以有几个钩子函数,
bind:只调用一次,在指令第一次绑定到元素上时调用。
update: 在 bind 之后立即以初始值为参数第一次调用,之后每当绑定值变化时调用,参数为新值与旧值。
unbind:只调用一次,在指令从元素上解绑时调用。
例如1
2
3
4
5
6
7
8
9
10
11
12
13
14
Vue.directive('my-directive', {
bind: function () {
// 准备工作
// 例如,添加事件处理器或只需要运行一次的高耗任务
},
update: function (newValue, oldValue) {
// 值更新时的工作
// 也会以初始值为参数调用一次
},
unbind: function () {
// 清理工作
// 例如,删除 bind() 添加的事件监听器
}
})
注册后就可以在模板中调用1
<div v-my-directive ="someValue" > </div >
如果只需要调用update函数,那么就只需要传一个函数就可以 例如1
2
3
Vue.directive('my-directive', function (value) {
// 这个函数用作 update()
})
同时,this对象暴露的属性如下
官方例子1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<div id ="demo" v-demo:hello.a.b ="msg" > </div >
Vue.directive('demo', {
bind: function () {
console.log('demo bound!')
},
update: function (value) {
this.el.innerHTML =
'name - ' + this.name + '<br > ' +
'expression - ' + this.expression + '<br > ' +
'argument - ' + this.arg + '<br > ' +
'modifiers - ' + JSON.stringify(this.modifiers) + '<br > ' +
'value - ' + value
}
})
var demo = new Vue({
el: '#demo',
data: {
msg: 'hello!'
}
})
指令传值,如果指令需要传多个值可以使用对象字面量传值,例如:1
2
3
4
5
6
7
如果指令需要多个值,可以传入一个 JavaScript 对象字面量。记住,指令可以使用任意合法的 JavaScript 表达式:
<div v-demo ="{ color: 'white', text: 'hello!' }" > </div >
Vue.directive('demo', function (value) {
console.log(value.color) // "white"
console.log(value.text) // "hello!"
})
点击查看demo
四、监听数据变化 1.$watch 和 computed 可以监听数据变动
例子:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<div id ="demo" > {{fullName}}</div >
var vm = new Vue({
el: '#demo',
data: {
firstName: 'Foo',
lastName: 'Bar',
fullName: 'Foo Bar'
}
})
vm.$watch('firstName', function (val) {
this.fullName = val + ' ' + this.lastName
})
vm.$watch('lastName', function (val) {
this.fullName = this.firstName + ' ' + val
})
vue 给了更高的方案是 computed 计算1
2
3
4
5
6
7
8
9
10
11
12
var vm = new Vue({
el: '#demo',
data: {
firstName: 'Foo',
lastName: 'Bar'
},
computed: {
fullName: function () {
return this.firstName + ' ' + this.lastName
}
}
})
setter和getter
默认会去getter这个属性 ,当你设置属性是会调用setter
例如:1
2
3
4
5
6
7
8
9
10
11
12
13
14
computed: {
fullName: {
// getter
get: function () {
return this.firstName + ' ' + this.lastName
},
// setter
set: function (newValue) {
var names = newValue.split(' ')
this.firstName = names[0]
this.lastName = names[names.length - 1]
}
}
}
点击查看demo
五、过滤器 过滤器实际上就是数据在显示之前做的处理,目前后端用的比较多,也称为拦截器. 语法
message显示之前执行capitalize 过滤.
1
2
3
4
串联过滤
{{ message | filterA | filterB }}
参数传递,这里字符串 'arg1' 将传给过滤器作为第二个参数,表达式 arg2 的值在计算出来之后作为第三个参数。
{{ message | filterA 'arg1' arg2 }}
自定义过滤器
类似于自定义指令,可以用全局方法 Vue.filter() 注册一个自定义过滤器,它接收两个参数:过滤器 ID 和过滤器函数。过滤器函数以值为参数,返回转换后的值:
1
2
3
4
5
6
<span v-text ="message | reverse" > </span >
Vue.filter('reverse', function (value) {
return value.split('').reverse().join('')
})
任意参数的过滤器
1
2
3
4
5
6
Vue.filter('wrap', function (value, begin, end) {
return begin + value + end
})
<span v-text ="message | wrap 'before' 'after'" > </span >
这里要说明一点,过滤器需要在创建vue对象之前声明,否则你new vue的时候,过滤器还没创建,肯定不会响应的.
点击查看demo
六、表单控件绑定 1) Text1
2
3
4
5
6
7
8
9
10
11
12
13
<div id ="Text-demo" >
<span > My Name Is {{myname}}</span >
<br >
<input type ="text" v-model ="myname" placeholder ="Edit My Name" >
</div >
<script >
new Vue({
el:'#Text-demo' ,
data:{
msg:'Great Boy'
}
})
</script >
2) Textarea
1
2
3
4
5
6
7
8
9
10
11
12
13
<div id ="Textarea-demo" >
<span > My Name Is {{myname}}</span >
<br >
<textarea v-model ="myname" placeholder ="Edit My Name" > </textarea >
</div >
<script >
new Vue({
el:'#Textarea-demo' ,
data:{
msg:'Great Boy'
}
})
</script >
3) Checkbox
1
2
3
4
5
6
7
8
9
10
11
12
13
<div id ="Checkbox-demo" >
<input type ="checkbox" id ="checkbox" v-model ="checked" > <label for ="checkbox" > {{ checked }}</label >
<input type ="checkbox" id ="checkbox-2" v-model ="checked2" > <label for ="checkbox-2" > {{ checked2 }}</label >
</div >
<script >
new Vue({
el:'#Checkbox-demo' ,
data:{
checked: true ,
checked2: false
}
})
</script >
4) Radio
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<h2 > Radio</h2 >
<div id ="Radio-demo" >
<input type ="radio" id ="one" value ="One" v-model ="picked" >
<label for ="one" > One</label >
<br >
<input type ="radio" id ="two" value ="Two" v-model ="picked" >
<label for ="two" > Two</label >
<br >
<span > Picked: {{ picked }}</span >
</div >
<script >
new Vue({
el:'#Radio-demo' ,
data:{
picked: true
}
})
</script >
点击查看demo
七、动画过渡
官方定义-> 通过 Vue.js 的过渡系统,可以在元素从 DOM 中插入或移除时自动应用过渡效果。Vue.js 会在适当的时机为你触发 CSS 过渡或动画,你也可以提供相应的 JavaScript 钩子函数在过渡过程中执行自定义的 DOM 操作。
过渡就是在给数据做变化的时候,是dom有一定的衔接动画
示例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
<!DOCTYPE html>
<html >
<head >
<meta charset ="utf-8" />
<meta http-equiv ="X-UA-Compatible" content ="IE=edge" />
<title > 前端观察</title >
<meta name ="description" content ="专注于网站前端设计与开发" />
<meta name ="HandheldFriendly" content ="True" />
<meta name ="viewport" content ="width=device-width, initial-scale=1.0" />
<meta name ="MobileOptimized" content ="320" >
<script type ="text/javascript" src ="vue.js" > </script >
</head >
<body >
<style >
.expand-transition {
transition : all .3s ease;
height : 30px ;
padding : 10px ;
background-color : #eee ;
overflow : hidden;
}
.expand-enter , .expand-leave {
height : 0 ;
padding : 0 10px ;
opacity : 0 ;
}
</style >
<div id ="test-container" >
<div v-if ="show" transition ="expand" > hello</div >
<button @click ="show = !show" > Toggle</button >
</div >
<script >
new Vue({
el:'#test-container' ,
data:{
show:true ,
}
})
</script >
</body >
</html >
点击查看demo
八、组件 组件可以说是我除了绑定渲染比较关注的一定地方,因为我一直认为开发就应该以组件的模式开发,这样维护起来比较方便,当需要改程序的时候,改一个地方就只改一个地方就好. 这也是我比较推崇组件开发的原因之一, fis目前已经很好的可以支持组件模式开发的构建,例如fis的 widget,当开发的时候可以把一个页面切分成N个widget,每一个widget可以由 html,css,js构成,当然这些不是必须的.
接下来看看vue的组件 官方定义->组件(Component)是 Vue.js 最强大的功能之一。组件可以扩展 HTML 元素,封装可重用的代码。在较高层面上,组件是自定义元素,Vue.js 的编译器为它添加特殊功能。在有些情况下,组件也可以是原生 HTML 元素的形式,以 is 特性扩展。
构造方式用Vue.extend()
,并且需要Vue.component
注册
1
2
3
var MyComponent = Vue.extend({
});
Vue.component('my-component' , MyComponent)
组件构造之后就可以通过 形式使用,需要确保初始化之前注册了组件
Vue提示-对于自定义标签名字,Vue.js 不强制要求遵循 W3C 规则(小写,并且包含一个短杠),尽管遵循这个规则比较好。
示例:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
<!DOCTYPE html>
<html >
<head >
<meta charset ="utf-8" />
<meta http-equiv ="X-UA-Compatible" content ="IE=edge" />
<title > 前端观察</title >
<meta name ="description" content ="专注于网站前端设计与开发" />
<meta name ="HandheldFriendly" content ="True" />
<meta name ="viewport" content ="width=device-width, initial-scale=1.0" />
<meta name ="MobileOptimized" content ="320" >
<script type ="text/javascript" src ="vue.js" > </script >
</head >
<body >
<div id ="test-container" >
<my-component > </my-component >
</div >
<script >
new Vue({
el:'#test-container' ,
data:{
msg:'Great Boy'
}
})
var MyComponent = Vue.extend({
template: '<div>A custom component!</div>'
})
Vue.component('my-component' , MyComponent)
new Vue({
el: '#test-container'
})
</script >
</body >
</html >
渲染为
1
2
3
<div id ="test-container" >
<div > A custom component!</div >
</div >
看到这里,我有几个问题 1,如何传给组件传递数据? 2,如何给组件打包成一个文件,或者一个文件夹? 3,能不能不用template,直接吧模板写在html里呢,毕竟用字符串拼接html是很累而且不友好的工作 带着这两个问题继续看文档
局部注册,可以在某一个组件内部注册一个组件,语法1
2
3
4
5
6
7
8
var Child = Vue.extend({ })
var Parent = Vue.extend({
template: '...' ,
components: {
'my-component' : Child
}
})
还可以
1
2
3
4
5
6
7
8
9
10
11
12
Vue.component('my-component' , {
template: '<div>A custom component!</div>'
})
var Parent = Vue.extend({
components: {
'my-component' : {
template: '<div>A custom component!</div>'
}
}
})
可以通过以下方式传递数据,MyComponent 所有的实例将共享同一个 data 对象
1
2
3
4
var data = { a: 1 }
var MyComponent = Vue.extend({
data: data
})
还可以让函数返回数据
1
2
3
4
5
var MyComponent = Vue.extend({
data: function ( ) {
return { a: 1 }
}
})
模板解析
引用官网 ->Vue 的模板是 DOM 模板,使用浏览器原生的解析器而不是自己实现一个。相比字符串模板,DOM 模板有一些好处,但是也有问题,它必须是有效的 HTML 片段。一些 HTML 元素对什么元素可以放在它里面有限制。常见的限制: a 不能包含其它的交互元素(如按钮,链接) ul 和 ol 只能直接包含 li select 只能包含 option 和 optgroup table 只能直接包含 thead, tbody, tfoot, tr, caption, col, colgroup tr 只能直接包含 th 和 td 在实际中,这些限制会导致意外的结果。尽管在简单的情况下它可能可以工作,但是你不能依赖自定义组件在浏览器验证之前的展开结果。例如 … 不是有效的模板,即使 my-select 组件最终展开为 … 。 另一个结果是,自定义标签(包括自定义元素和特殊标签,如 、、 )不能用在 ul, select, table 等对内部元素有限制的标签内。放在这些元素内部的自定义标签将被提到元素的外面,因而渲染不正确。
有这么多限制….
数据传递 刚才的数据传递问题可以通过 props来传递
1
2
3
4
5
6
7
Vue.component('child' , {
props: ['msg' ],
template: '<span>{{ msg }}</span>'
})
1
<child msg ="hello!" > </child >
这个其实是我想要的,因为从组件一般都有引用之处,也及时在这是才开始传递数据的
父子组件通信
子组件可以用 this.$parent 访问它的父组件。根实例的后代可以用 this.$root 访问它。父组件有一个数组 this.$children,包含它所有的子元素。 尽管可以访问父链上任意的实例,不过子组件应当避免直接依赖父组件的数据,尽量显式地使用 props 传递数据。另外,在子组件中修改父组件的状态是非常糟糕的做法,因为: 这让父组件与子组件紧密地耦合; 只看父组件,很难理解父组件的状态。因为它可能被任意子组件修改!理想情况下,只有组件自己能修改它的状态。
编写可复用组件
在编写组件时,记住是否要复用组件有好处。一次性组件跟其它组件紧密耦合没关系,但是可复用组件应当定义一个清晰的公开接口。
Vue.js 组件 API 来自三部分——prop,事件和 slot:
prop 允许外部环境传递数据给组件;
事件 允许组件触发外部环境的 action;
slot 允许外部环境插入内容到组件的视图结构内。
上面组件的API非常重要,这也是我们写组件的第二个好处,第一个是拆分好了,好维护,第二个是可以复用.
至此组件大部分的知识都已经学完, 面向组件开发也是我们开发中最重要的一种方式. 但是上面提的3个问题,还有一个问题2没有解决,其实我大概看的了一下构建模式里,可以把这个组件写成.vue后,可以通过打包工具去合并.那么如果拆分呢?回头看到构建在说. 用组件写个小的demo吧,温习一下,组件的内容较多,需要仔细研究.点击查看demo
九、插件 组件其实是我最感性的内容之一,好的模块拆分就看它了,不过插件也很重要,插件主要是来写一些复用性强的工具,例如ajax,router,chart等等 开发的种类:
插件开发方法: 1.插件需要对外接口install 2.用use方法注册,就可以使用了