vue的引用
通过script标签的方式进行引用。
1
| <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
|
组件
vue
的核心功能之一就是组件
组件基本分类
根组件的创建
通过 vue
提供的构造函数可以实例化出来一个跟组件实例对象
1
| let app = new Vue(options);
|
应用最顶层的组件,一般情况下,一个独立的应用有且只有一个根组件(节点)
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
| <!DOCTYPE html> <html lang="en">
<head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <script src="./js/vue.js"></script> </head>
<body> <div id="app"></div> <script> let app = new Vue({ template: '<div>xiaokang.me</div>' }) app.$mount('#app') </script> </body>
</html>
|
上面发生了什么?
其实通过实例化Vue对象,传入配置字段template
相当于定义了一个模板,通过Vue对象提供的$mount
方法,将其添加到指定的标签元素中。类似于createElement
与appendChild
的概念。
可复用的功能组件
通过 Vue
提供的静态方法 component
窗口可复用的功能组件
1
| let component1 = Vue.component(options)
|
组件配置选项:https://cn.vuejs.org/v2/api/
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 lang="en">
<head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title>
</head>
<body> <div id="app"></div> <script src="./js/vue.js"></script> <script> Vue.component('tab', { template: `<div>这是一个tab选项卡</div>` }) let app = new Vue({ template: ` <div> <p>xiaokang.me</p> <tab /> <br /> </div> ` })
app.$mount('#app') </script> </body>
</html>
|
el选项
如果提供了 el,且又没有提供template,那么会自动把el的innerHTML作为template。
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
| <!DOCTYPE html> <html lang="en">
<head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title>
</head>
<body> <div id="app"> <h1>xiaokang.me</h1> <tab> </div> <script src="./js/vue.js"></script> <script> Vue.component('tab', { template: `<div>这是一个tab选项卡</div>` }) let app = new Vue({ el: '#app' }) </script> </body>
</html>
|
data与更新
使用 vue 的原因,在于数据,页面会根据不同的数据显示不同的内容
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 lang="en">
<head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title>
</head>
<body>
<div id="app"> <h1>xiaokang.me</h1> <h2>name:{{name}}</h2> <tab> </div> <script src="./js/vue.js"></script> <script> Vue.component('tab', { template: `<div>这是一个tab选项卡</div>` }) let app = new Vue({ el: '#app', data: { name: 'Xioakang', age: 18 } }) </script> </body>
</html>
|
将数据传入到Vue对象选项中的data
字段,在模板里只需要通过{{}}`即可调用到该属性,例如`{{name}}
表示调用data.name
,其数据来源于data中的数据,所以不需要写data.name
。
Vue会把data
传入的属性挂载到Vue对象中,因此属性命名时不可以与原有属性冲突。
关于数据的更新,只需要改动属性即可。如图:
拦截数据
简单来说,就是数据修改时拦截数据,这样就实现了只关注数据的修改,而不关心渲染。
在 vue3 之前,数据的监听是通过 Object.defineProperty
方法来实现的,但是该方法只能监听拦截单个数据,对于对象新增属性无法监听拦截。所以,对于数据对象中新增的属性,我们需要调用 vue 提供的方法来进行处理
对vue的模拟如下:
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
| <!DOCTYPE html> <html lang="en">
<head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head>
<body>
<script> let obj1 = { x: 1, y: 2 } function render() { console.log('渲染了!'); } let obj2 = Object.assign({}, obj1) Object.defineProperty(obj1, 'x', { set(newVal) { obj2.x = newVal render() }, get() { return obj2.x } }) obj1.x = 2 console.log(obj1.x); </script> </body>
</html>
|
通过 Object.defineProperty
监听拦截中存在一些问题
- 属性新增属性
- 数组方法:push、pop、shift、unshift、splice、sort、reverse
- 数组新增值:[]
- 数组 length 属性
以上的操作中并不会触发监听拦截
vue
对数组中的 push
、pop
等方法进行重新包装,所以在 vue
中调用这些方法,可以对数组的修改进行监听拦截
https://cn.vuejs.org/v2/guide/list.html#%E5%8F%98%E5%BC%82%E6%96%B9%E6%B3%95-mutation-method
为了解决上述问题,vue2提供了set方法,其原理如下:
1 2 3 4 5 6 7 8 9 10 11
| function set(key, value) { Object.defineProperty(obj1, key, { set(newVal) { value = newVal; render(); }, get() { return value; } }) }
|
此时通过调用set方法即可对新属性进行拦截。
在vue中有两种方式调用set方法:
1 2 3
| Vue.set(app.user, 'age', 19)
app.$set(app.user, 'age', 19)
|