文章内容输出来源 拉勾教育大前端高薪训练营
本文主要围绕 Composition API
来讲解如何使用,分别是以下几个API 函数, 通过学习,可以让你可以更快上手 Composition API
,掌握 Vue.js 3.0
的新特性。
安装Vue3.0 ,体验 createApp 的使用
npm install vue@3.0.0-rc.1
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Documenttitle>
head>
<body>
<div id="app">
x: {
{ position.x }}
y: {
{ position.y }}
div>
<script type="module">
import {
createApp } from './node_modules/vue/dist/vue.esm-browser.js'
const app = createApp({
data () {
return {
position: {
x: 0,
y: 0
}
}
}
})
console.log(app)
app.mount('#app')
script>
body>
html>
Vue 3.0
和 Vue2.0
的区别,成员要少很多,没有$开头, 使用方式和以前一样
setUp 函数
import {
createApp, reactive, onMounted, onUnmounted } from './node_modules/vue/dist/vue.esm-browser.js'
const app = createApp({
setup () {
// 第一个参数 props
// 第二个参数 context, attrs, emit, slots
const position = reactive({
x: 0,
y: 0
})
const update = e => {
position.x = e.pageX;
position.y = e.pageY;
}
onMounted (() => {
window.addEventListener('mousemove', update)
})
onUnmounted (() => {
window.removeEventListener('mousemove', update)
})
return {
position
}
}
})
console.log(app)
app.mount('#app')
当鼠标移动的时候显示鼠标移动的位置,当组件卸载时,鼠标移动的事件也要移除
将获取鼠标位置的方法封装到一个函数中,优化代码
import {
createApp, reactive, onMounted, onUnmounted } from './node_modules/vue/dist/vue.esm-browser.js'
function useMousePosition () {
// 第一个参数 props
// 第二个参数 context, attrs, emit, slots
const position = reactive({
x: 0,
y: 0
})
const update = e => {
position.x = e.pageX;
position.y = e.pageY;
}
onMounted (() => {
window.addEventListener('mousemove', update)
})
onUnmounted (() => {
window.removeEventListener('mousemove', update)
})
return position
}
const app = createApp({
setup () {
const position = useMousePosition()
return {
position
}
}
})
console.log(app)
app.mount('#app')
都是创建响应式数据的
先看上一节出现的小问题
import {
createApp, reactive, onMounted, onUnmounted } from './node_modules/vue/dist/vue.esm-browser.js'
function useMousePosition () {
// 第一个参数 props
// 第二个参数 context, attrs, emit, slots
const position = reactive({
x: 0,
y: 0
})
const update = e => {
position.x = e.pageX;
position.y = e.pageY;
}
onMounted (() => {
window.addEventListener('mousemove', update)
})
onUnmounted (() => {
window.removeEventListener('mousemove', update)
})
return position
}
const app = createApp({
setup () {
// const position = useMousePosition()
const {
x, y} = useMousePosition()
return {
x,
y
}
}
})
console.log(app)
app.mount('#app')
对useMousePosition
进行解构后,数据不是响应式的了
这里的 position
是响应式对象,因为在useMousePosition
中调用了reactive
函数,把传入的对象包装成了 Proxy
对象,也就是说 position
就是 proxy
对象,当 position
访问 x, y的时候会调用代理中的 getter
拦截收集依赖,变化的时候会调用 setter
使用 toRefs
import {
createApp, reactive, onMounted, onUnmounted, toRefs } from './node_modules/vue/dist/vue.esm-browser.js'
...
return toRefs(position)
toRefs原理
toRefs 要求传入的参数 必须为代理对象,当前的 position
就是 reactive
返回的代理对象,如果不是的话,会发出警告,提示传递代理对象,
内部会创建一个新的对象,然后遍历传入代理对象的所有属性,把所有属性的值都转换成响应式对象,相当于将postion
的x, y
属性转换成响应式对象,
挂在到新创建的对象上,最后把新创建的对象返回。内部为代理对象的每一个属性创建一个具有 value 属性,value属性具有 getter,setter
, getter
中返回对象属性的值,
setter中给代理对象赋值。所以返回的每一个属性都是响应式的
ref 把普通数据转转换成响应式数据,ref 可以把基本类型包装成响应式数据
<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 () {
const count = ref(0)
return {
count,
increase: () => {
count.value++
}
}
}
createApp({
setup() {
return {
...useCount()
}
}
}).mount('#app')
script>
第一种用法
第二种用法
const count = ref(1)
const plusOne = computed({
get: () => {
count.value + 1
},
set: val => {
conut.value = val - 1
}
})
<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: false
}
]
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>
Watch 的三个参数
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Documenttitle>
head>
<body>
<div id="app">
请问一个 yes/no 的问题
<input v-model="question">input>
{
{answer}}
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(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>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Documenttitle>
head>
<body>
<div id="app">
<button @click="increase">increasebutton>
<button @click="stop">stopbutton>
<br>
{
{count}}
div>
<script type="module">
import {
createApp, ref, watchEffect } from './node_modules/vue/dist/vue.esm-browser.js'
createApp({
setup() {
const count = ref(0)
const stop = watchEffect(() => {
console.log(count.value)
})
return {
count,
stop,
increase: () => {
count.value++
}
}
}
}).mount('#app')
script>
body>
html>
完整代码请点击这里