一、案例1 —— 获取鼠标位置
-
createApp :createApp 的作用是创建一个 vue 对象,里面可以传入一个选项,注意 createApp 传入选项中的 data 必须是函数形式 data(){}
-
setup: setup 是 composition-api 的入口
- setup 是在 props 被解析完毕,在组件实例被创建之前执行的,所以在 setup 内部无法通过 this 获取到组件实例,也就是说 setup 是在 beforeCreate 和 created 之间执行的,所以在 beforeCreate 和 created 之间的代码都可以放到 setup 函数中
- setup 有两个参数,第一个参数 props,第二个参数 context,context 是一个对象,有三个属性,分别是 attrs、emit、slots
- setup 还需要返回一个对象,可以使用在模版、methods、computed、以及所有钩子函数中
- 在 setup 中也可以使用组件生命周期的钩子函数,但是必须在前面加上 on
-
reactive:reactive 把一个对象转换成响应式对象,并且该对象的嵌套属性也会转换为响应式对象,返回的是一个 proxy 对象,reactive 和 Vue.observable 类似
-
toRefs: toRefs 可以把一个响应式对象的所有属性的值转换成响应式的
- toRefs 传入的对象必须是一个 proxy 代理对象,它内部会创建一个新的对象,然后来遍历传入代理对象的所有属性,把所有属性的值转换为响应式对象,然后挂载到新创建的对象上,并返回
- toRefs 内部就是为传入的代理对象的每一个属性,创建一个带有 value 属性的对象,该对象是响应式的,value 属性具有 get 和 set 方法,和 ref 方法类似
- 在模版中使用的时候可以把 value 省略,但是在代码中写的时候是不可以省略的
案例代码
<!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">
x: {{ x }} <br>
y: {{ y }}
</div>
<script type="module">
// vue.esm-browser 是 vue3 完整版
import { createApp, reactive, onMounted, onUnmounted, toRefs } from './node_modules/vue/dist/vue.esm-browser.js'
// 获取鼠标位置的方法
function useMousePosition() {
// reactive 把一个对象转换成响应式对象,并且该对象的嵌套属性也会转换为响应式对象,返回的是一个 proxy 对象
// reactive 和 Vue.observable 类似
const position = reactive({
x: 0,
y: 0
})
const update = e => {
position.x = e.pageX
position.y = e.pageY
}
// 在 setup 中也可以使用组件生命周期的钩子函数,但是必须在前面加上 on
onMounted(() => {
window.addEventListener('mousemove', update)
})
onUnmounted(() => {
window.removeEventListener('mousemove', update)
})
// toRefs 可以把一个响应式对象的所有属性的值转换成响应式的
// toRefs 传入的对象必须是一个 proxy 代理对象,它内部会创建一个新的对象,然后来遍历传入代理对象的所有属性,
// 把所有属性的值转换为响应式对象,然后挂载到新创建的对象上,并返回
// 内部就是为传入的代理对象的每一个属性,创建一个带有 value 属性的对象,该对象是响应式的,value 属性具有 get 和 set 方法,和 ref 方法类似
// 在模版中使用的时候可以把 value 省略,但是在代码中写的时候是不可以省略的
return toRefs(position)
}
// createApp 的作用是创建一个 vue 对象,里面可以传入一个选项
// 注意 createApp 传入选项中的 data 必须是函数形式 data(){}
const app = createApp({
// setup 是 composition-api 的入口,
// setup 是在 props 被解析完毕,在组件实例被创建之前执行的,所以在 setup 内部无法通过 this 获取到组件实例
// 也就是说 setup 是在 beforeCreate 和 created 之间执行的,所以在 beforeCreate 和 created 之间的代码都可以放到 setup 函数中
// setup 有两个参数
// 第一个参数 props
// 第二个参数 context,context 是一个对象,有三个属性,分别是 attrs、emit、slots
// setup 还需要返回一个对象,可以使用在模版、methods、computed、以及所有钩子函数中
setup() {
// position 被解构出来的 x,y 是没有具备响应式的,就只是两个基本类型的变量
const { x, y } = useMousePosition()
return {
x,
y
}
}
})
console.log(app)
// 把实例挂载到 id 为 app 的 div 中
app.mount('#app')
</script>
</body>
</html>
二、案例2 —— 点击按钮加加
- ref :ref 方法可以把一个基本类型的数据转化为响应式对像,内部就是将该基本类型的值转化为一个带有 value 属性的对象,并且为这个值创建 get、set 方法
<!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">
<button @click="increase">按钮</button>
<span>{{ count }}</span>
</div>
<script type="module">
import { createApp, ref } from './node_modules/vue/dist/vue.esm-browser.js'
function useCount() {
// ref 方法可以把一个基本类型的数据转化为响应式对像
const count = ref(0) // count : { value : 0 }
return {
count,
increase: () => {
count.value++
}
}
}
createApp({
setup() {
return {
...useCount()
}
}
}).mount('#app')
</script>
</body>
</html>
三、案例3 —— 未完成代办事项
- computed 两种用法
- 传入一个获取值的函数,函数内部依赖响应式的数据,当依赖的数据发生变化后会重新执行该函数获取数据
- 传入一个响应式对象,这个对象具有 get 和 set ,返回一个不可变的响应式对象
- computed 的目的是创建一个响应式数据,这个响应式的数据依赖于其他响应式数据,返回的是一个不可变的响应式对象,类似于使用 ref 创建的对象,只有一个 value 属性
<!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">
<button @click="push">按钮</button>
未完成:{{ activeCount }}
</div>
<script type="module">
import { createApp, reactive, computed } from './node_modules/vue/dist/vue.esm-browser.js'
const data = [
{ text: '看书', completed: false },
{ text: '敲代码', completed: false },
{ text: '约会', completed: true }
]
// computed 两种用法
// 1、传入一个获取值的函数,函数内部依赖响应式的数据,当依赖的数据发生变化后会重新执行该函数获取数据
// computed 函数返回的是一个不可变的响应式对象,类似于使用 ref 创建的对象,只有一个 value 属性
// computed 的目的是创建一个响应式数据,这个响应式的数据依赖于其他响应式数据
// 2、传入一个响应式对象,这个对象具有 get 和 set ,返回一个不可变的响应式对象
createApp({
setup() {
const todos = reactive(data)
// 返回待办事项个数
const activeCount = computed(() => {
return todos.filter(item => !item.completed).length
})
return {
activeCount,
push: () => {
todos.push({
text: '开会',
completed: false
})
}
}
}
}).mount('#app')
</script>
</body>
</html>
四、案例4 —— 返回 yes or no
-
watch 三个参数:
- 监听的数据
- 监听到数据变化后执行的回调函数,该函数有两个参数,分别是新值和旧值
- 选项对象,deep 和 immediate
-
watch 的返回值是取消监听的函数
-
watch 的使用和过去的 this.$watch 是一样的,这是第一个参数不在是字符串,而是 ref 或者 reactive 创建的响应式对象
<!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">
<p>
请问一个 yes/no 的问题:
<input v-model="question">
</p>
<p>{{ answer }}</p>
</div>
<script type="module">
import { createApp, ref, watch } from './node_modules/vue/dist/vue.esm-browser.js'
createApp({
setup() {
const question = ref('')
const answer = ref('')
// watch 三个参数:
// 1、监听的数据
// 2、监听到数据变化后执行的回调函数,该函数有两个参数,分别是新值和旧值
// 3、选项对象,deep 和 immediate
// watch 的返回值是取消监听的函数
watch(question, async (newValue, oldValue) => {
const response = await fetch('https://www.yesno.wtf/api')
const data = await response.json()
answer.value = data.answer
})
return {
question,
answer
}
}
}).mount('#app')
</script>
</body>
</html>
五、案例4 —— 监听 count 变化
-
watchEffect 是 watch 函数的简化版本,也是用来监视数据的变化,内部实现和 watch 调用了同一个函数 doWatch
-
不同的是 watchEffect 没有第二个回调函数的参数,watchEffect 接受一个函数作为参数,监听函数内部使用的响应式数据的变化,一旦变化,就执行一般该函数
-
watchEffect 也会返回了一个取消监听的函数
<!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">
<button @click="increase">increase</button>
<button @click="stop">stop</button>
<br>
{{ count }}
</div>
<script type="module">
import { createApp, ref, watchEffect } from './node_modules/vue/dist/vue.esm-browser.js'
// watchEffect 是 watch 函数的简化版本,也是用来监视数据的变化,内部实现和 watch 调用了同一个函数 doWatch
// 不同的是 watchEffect 没有第二个回调函数的参数,watchEffect 接受一个函数作为参数,监听函数内部使用的响应式数据的变化,一旦变化,就执行一般该函数
// 也返回了一个取消监听的函数
createApp({
setup() {
const count = ref(0)
const stop = watchEffect(() => {
// 该回调函数初始的时候会被执行一次,在 count 发生变化的时候会再次被调用
console.log(count.value)
})
return {
count,
stop,
increase: () => {
count.value++
}
}
}
}).mount('#app')
</script>
</body>
</html>