VUE|创建一个基础的VUE应用
1 应用实例
参考官方文档
示例
const {createApp} = Vue
// 通过createApp创建一个应用实例
const app = createApp({
/* 选项 */
})
console.log(app)
分析打印结果, 可知
- 应用实例是一个
对象
- 没有_开头的是公开属性/方法
- 以_开头的是私有属性/方法(也就是Vue内部使用的)
component: 定义组件
directive: 定义指令
use: 定义插件
---
mount: 挂载
unmount: 卸载
2 挂载
1) 基本语法
一个应用实例
必须在调用了 .mount() 方法后才会渲染
- 传入参数: 可以是一个 CSS 选择器字符串(常用) 或者 一个实际的 DOM 元素
- 返回值: 根组件实例
// 挂载应用, 返回根组件实例
const instance = app.mount('#app')
console.log(instance)
分析结果. 可知
- instance是一个Proxy对象
- 在选项中定义的内容会被挂载到instance对象上
示例
<!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="../node_modules/vue/dist/vue.global.js"></script>
</head>
<body>
<div id="app">{{msg}}</div>
<script>
const { createApp } = Vue
const app = createApp({
data() {
return {
msg: 'hello',
}
},
})
console.log(app)
// app.mount('#app') 常用
// 由于mount返回的不是app实例本身, 因此mount的调用需要放在链式调用的最后
const vm = app.mount(document.querySelector('#app'))
console.log(vm)
</script>
</body>
</html>
2) 根组件实例
之前, 我们通过调试工具改变data中的定义的状态时, 视图会响应变化.
如何通过代码实现同样的功能呢?
示例
setTimeout(() => {
instance.msg = 'world'
}, 1000)
在data中定义的状态会被代理到instance
上.
当改变代理对象的状态值时, 可以拦截到set
操作, 从而自定义set
操作.
在自定义的set
操作中更新DOM
3) 响应式原理初步
proxy对象
<!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>
const obj = {
name: 'xiaoming',
0: 'test',
}
// 对象访问属性必须使用[]语法的两种情况
// 1. 属性名是一个无效的标识符
// 2. 属性名是一个变量
// console.log(obj[0])
let key = 'name'
// console.log(obj[key]) // obj.name
// 创建代理对象的过程叫做属性的劫持
// 1. 将普通对象(目标对象)的每一个属性拦截, 添加自定义的getter和setter
// 2. 后续对代理对象属性的设置, 触发自定义setter, 在setter中更新页面
// p对象可以认为包含任意属性, 代理对象有效的属性跟目标对象是一致
const p = new Proxy(obj, {
get(target, key) {
// 当访问p对象的属性时, 调用该函数, 将该函数的返回值做为表达式的结果
console.log('访问xx属性')
// target: 目标对象
// key: 代理对象的属性
return target[key]
},
set(target, key, value) {
console.log('设置xx属性')
target[key] = value
},
})
console.log(p)
// 对于普通对象而言, 访问的过程是由js引擎控制
// console.log(obj.name)
// 自定义的访问过程, 叫属性的getter操作(元编程)[meta]
</script>
</body>
</html>
示例
<script>
const data = {
msg: 'hello',
}
const pData = new Proxy(data, {
get: function (target, key) {
return target[key]
},
set: function (target, key, value) {
target[key] = value
console.log('更新DOM')
document.querySelector('#app').innerHTML = value
},
})
setTimeout(() => {
pData.msg = 'world'
}, 1000)
console.log(data, pData)
</script>
data
模拟原始数据pData
模拟代理数据
初次渲染时, 从data
中获取数据, 后续修改代理对象的值, 会被拦截到, 并且更新DOM
4) 注意点
- 如果不调用.mount(), 不会解析模板
- mount()方法应该在应用配置的最后被调用
3 基本选项
1) 状态
data选项
- data选项必须是一个函数(在介绍组件时再详细讨论)
- 在函数中返回一个对象, 在对象中定义状态
- 在data中定义的状态, 可以在模板中使用
示例
const app = createApp({
data() {
return {
msg: 'hello',
}
},
})
2) 方法
methods选项
- 语法: methods中定义方法
- 作用: 修改data中的状态
示例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<script src="../node_modules/vue/dist/vue.global.js"></script>
</head>
<body>
<div id="app">
<button v-on:click="increment">点击+1: {{count}}</button>
</div>
<script>
const { createApp } = Vue
const app = createApp({
data() {
return {
count: 0,
}
},
methods: {
increment() {
// 该函数中的this指向当前根组件实例instance
console.log(this)
this.count++
},
},
})
const instance = app.mount('#app')
</script>
</body>
</html>
- methods中定义的方法要求是普通函数 在普通函数中通过this拿到当前实例对象
3) 小结
重要结论
- 状态就是用来 保存 数据的
- 方法就是用来 修改 数据的