内容
创建Vue3.0工程
- 使用
vue-cli
创建
// 确保@vue/cli版本在4.5.0以上
vue --version
// 安装或者升级你的@vue/cli
npm install -g @vue/cli
// 创建(xxx为项目名)
vue create xxx
// 启动
cd xxx
npm run serve
- 使用
vite
创建
- 什么是vite
新一代前端构建工具 - 优势:
开发环境中无需打包操作,可以快速的冷启动
轻量快速的热重载
真正的按需编译,不再等待整个应用编译完成
// 创建工程(xxx为项目名)
npm init vite-app xxx
// 进入工程目录
cd xxx
// 安装依赖
npm install
// 运行
npm run dev
常用的composition api
setup
- vue3.0中一个新的配置项,
一个函数
- 组件中所用到的:
数据
、方法
均要配置在setup
中 setup
的返回值
:若返回一个对象
,则对象中的属性、方法,均在模板中可以直接使用
export default {
setup() {
// data
let name = 'AIpoem',
let age = 20,
// method
function sayHi() {
alert(`我叫${name},今年${age}岁!,你好`)
}
return {
name,
age,
sayHi
}
}
}
- ⚠️:
尽量不要跟vue2.x配置混用- vue2.x(data、method…)中可以访问到setup中的属性、方法
- 但
setup
中无法访问到vue2.x(data、method…) setup
不能是一个async
函数,否则其返回值
不再是return
的对象,而是promise
ref函数
- 语法:
const xxx = ref(initValue)
- 创建一个包含
响应式数据
的引用对象
- 在
js
中操作数据:xxx.value
- 在
模板
中读取数据:<div>{{xxx}}</div>
import {ref} from 'vue';
export default {
setup() {
// data
let name = ref('AIpoem')
let age = ref(20)
let job = reactive({
type: '开发人员'
salary: '10k'
})
// method
function changeInfo() {
name.value = 'poem'
age.value = 80
job.value.type = '设计师'
job.value.salary = '60k'
}
return {
name,
age,
job,
changeInfo
}
}
}
- ⚠️:
接收的数据可以是基本类型,也可以是对象类型- 基本类型的数据:响应式是依然通过
Object.defineProperty()
的get
和set
完成的 - 对象类型的数据:内部求助了vue3.0的一个新函数——
reactive函数
- 基本类型的数据:响应式是依然通过
reactive函数
- 作用:定义一个
对象
类型的响应式
数据(基本类型不要用它,要用ref
函数) - 语法:
const 代理对象 = reactive(源对象)
,返回一个代理对象(Proxy的实例对象)
- 内部基于es6的Proxy实现
import {ref,reactive} from 'vue';
export default {
setup() {
// data
let name = ref('AIpoem')
let age = ref(20)
let job = reactive({
type: '开发人员'
salary: '10k'
})
let hobby = reactive(['吃','喝','玩','乐'])
function changeInfo() {
name.value = 'poem'
age.value = 80
job.type = '设计师'
job.salary = '60k'
hobby[0] = '学'
}
return {
name,
age,
job,
hobby,
changeInfo
}
}
}
简化:
import {reactive} from 'vue';
export default {
setup() {
// data
let person = reactive({
name: 'AIpoem',
age: 20,
job: {
type: '开发人员'
salary: '10k'
},
hobby: ['吃','喝','玩','乐']
})
// method
function changeInfo() {
person.name = 'poem'
person.age = 80
person.job.type = '设计师'
person.job.salary = '60k'
person.hobby[0] = '学'
}
return {
person,
changeInfo
}
}
}
reactive对比ref
从定义数据角度对比:
ref
用来定义:基本
类型数据reactive
用来定义:对象/数组
类型数据
⚠️:ref
也可以用来定义对象/数组类型数据,它的内部会自动通过reactive
转为代理对象
从原理角度对比:
ref
通过Object.defineProperty()
的get
和set
来实现响应式(数据劫持)reactive
通过使用Proxy
来实现响应式(数据劫持),并通过Reflect
来操作源对象内部的数据
从使用角度对比:
ref
定义的数据:操作数据需要.value
,模板中可以直接读取不需要.value
reactive
定义的数据:操作数据与读取数据:均不需要.value
`
setup的两个注意点
setup
的执行时机
- setup在
beforeCreate()
之前执行一次 - setup里面的
this
是undefined
(在setup里写this是无效的)
- setup在
setup
的参数props
: 值为对象,包含了:组件外部传递
过来,且组件内部声明接收
了的属性context
: 上下文对象- attrs: 值为对象,包含了:组件
外部传递
过来,但没有在props配置中声明的属性
,相当于vue2中的this.$attrs
- slots: 收到的
插槽内容
,相当于vue2中的this.$slots
- emit: 分发
自定义事件
的函数,相当于vue2中的this.$emit
- attrs: 值为对象,包含了:组件
测试attrs:
// App.vue
<demo name='AIpoem' age=20></demo>
// Demo.vue
import { reactive } from 'vue';
export default {
props: ['name','age'],
setup(props,context) {
console.log('我是props',props);
console.log('我是context',context);
console.log('我是context中的attrs',context.attrs);
}
}
name
和age
都在props
中声明接收了,因此attrs
中没有:
若不声明接收age
// Demo.vue
import { reactive } from 'vue';
export default {
props: ['name'],
setup(props,context) {
console.log('我是props',props);
console.log('我是context',context);
console.log('我是context中的attrs',context.attrs);
}
}
则age
会在attrs
中出现:
emit使用:
// App.vue
<demo @my-event="handleEvent"></demo>
setup() {
function handleEvent(value) {
console.log(`触发了my-event事件,收到参数${value}`);
}
return {
handleEvent
}
}
// Demo.vue
<button @click="test">测试触发Demo组的my-event事件</button>
setup(props,context) {
function test() {
context.emit('my-event',123);
}
return {
test
}
}