文章目录
文章名称
提示:以本篇文章主要为了对比vue2.x,vue3.0,vue3.2在语法上的不同
1 文件结构
vue2.x写法
<template>
// 只能有一个根元素
<div></div>
</template>
<script >
export default {
....
}
</script>
vue3.0写法
<template>
// 不做限制
<div></div>
<div></div>
<div></div>
</template>
<script >
import {
reactive, ref, toRefs } from 'vue'
export default {
setup() {
const name = ref('张三')
const test = reactive({
name: '小李',
nikeName: '哈哈哈哈'
})
// ... 提出组合式api,方法,定义数据,生命周期函数,计算属性,监听等写在组合api里面
return {
name, test, ...toRefs(test)}
}
}
</script>
vue3.2写法
<template>
// 不做限制
<div></div>
<div></div>
<div></div>
</template>
<script setup>
import {
reactive, ref, toRefs } from 'vue'
// setup直接写在 script标签中,删除export default,也不用写return
// ... 提出组合式api,方法,定义数据,生命周期函数,计算属性,监听等写在组合api里面
const name = ref('张三')
const test = reactive({
name: '小李',
nikeName: '哈哈哈哈'
})
</script>
2 data声明
vue2.x写法
<script>
export default {
data() {
name: '张三',
obj: {
name: '李四',
sex: '男'
},
arr: [1, 2, 3]
}
}
</script>
在data中声明的变量为响应式数据,可直接在模板中使用
vue3.0写法
<script>
import {
ref, reactive, toRefs} from 'vue'
export default {
setup() {
cosnt name = ref('张三')
obj: {
name: '李四',
sex: '男'
},
arr: [1, 2, 3]
}
}
</script>
* 在3.x版本中要借助 ref 函数 和 reactive 函数 来定义响应式数据
* ref 函数只能定义可定义字符串,数字,对象类型的数据,但通常用来定义字符串和数字类型
* ref 函数定义的可在模板中直接使用,但是在 setup 中使用,要加上 .value
<template>
<div>{
{
testData }}</div>
</template>
<script>
import {
ref } from 'vue'
export default {
setup() {
const testData = ref('我是测试数据')
console.log(testData.value)
}
}
return {
testData }
</script>
* 通过 ref 定义的响应式数据,一定要使用 retrun 给return出去,否则无法在模板中使用
* reactive只能定义对象和数组,不能定义字符串和数字
* reactive 结合 toRefs,在 return 中结构
* 通常,我们把字符串和数字类型的普通变量,定义在对象中统一管理,因此,使用 reactive 和 toRefs 结合比较多
<template>
<div>page3</div>
<div>{
{
teatData.name }}</div>
<div>{
{
teatData.age }}</div>
<div>{
{
name }}</div>
<div>{
{
age }}</div>
</template>
<script setup>
import {
reactive, toRefs } from 'vue'
const teatData = reactive({
name: '小李',
age: 20
})
console.log(teatData.name)
console.log(teatData.age)
}
</script>
vue3.2写法
<template>
<div>page2</div>
<div>{
{
simpleData }}</div>
<div>{
{
testData.name }}</div>
<div>{
{
testData.age }}</div>
<div>{
{
name }}</div>
<div>{
{
age }}</div>
</template>
<script setup>
import {
ref, reactive, toRefs } from 'vue'
const simpleData = ref('我是测试数据')
const testData = reactive({
name: '小李',
age: 20
})
const {
name, age } = toRefs(testData)
console.log(testData.name)
console.log(testData.age)
console.log(name)
console.log(age)
</script>
<script>
export default {
name: 'page2'
}
</script>
* 在 vue3.2 版本中,不需要对 ref 和 reactive 声明的响应式数据 return,可直接在模板中使用
* toRfes只直接在业务代码中进行结构,并在模板中使用结构后的变量
- vue3.0 与 vue3.2 最大的不同就是: 定义的响应式数据不需要return,可直接在模板中使用,
3 method方法
vue2.0写法
<script>
export default {
method: {
testFun() {
console.log('1111')
}
}
}
</script>
vue3.0写法
<script>
export default {
setup() {
cosnt testFun = ()=> {
console.log('1111')
}
return {
testFun }
}
}
</script>
直接在 setup 中声明方法,必须用 retrun 导出,才能在模板中使用
vue3.2写法
<script setup>
cosnt testFun = ()=> {
console.log('1111')
}
</script>
不用通过 retrun 导出,可直接在模板中使用
3 computed方法
vue2.0写法
<script>
export default {
data() {
return {
count: 1,
doubleCount: null
}
},
computed: {
doubleCount() {
return this.count * 2
}
}
}
</script>
vue3.0写法
<script>
import {
ref,computed } from 'vue'
export default {
setup() {
cosnt count = ref(1)
const doubleCount = computed(() => {
return count.value * 2
})
retrun {
doubleCount }
}
}
</script>
vue3.2写法
<script setup>
import {
computed, ref} from 'vue';
const count = ref(1);
// 通过computed获得doubleCount
const doubleCount = computed(()=> {
return count.value * 2;
})
</script>
4 watch 用法
vue2.0写法
<script>
export default {
data() {
return {
state: {
count: 1,
count: 2
}
}
},
watch: {
state: {
handler(newVal, oldVal) {
console.log('newVal', newVal)
console.log('oldVal', oldVal)
},
immediate: true,
deep: true
},
'state.count1'(newVal, oldVal) {
console.log('newVal', newVal)
console.log('oldVal', oldVal)
}
}
}
</script>
vue3.0写法
<script>
import {
reactive, watch } from 'vue'
export default {
name: 'page5',
setup() {
const state = reactive({
const1: 1,
const2: 2
})
watch(
state,
(newVal, oldVal) => {
console.log('newVal', newVal)
console.log('oldVal', oldVal)
},
{
immediate: true, deep: true }
)
watch(
() => state.const1,
(newVal, oldVal) => {
console.log('newVal', newVal)
console.log('oldVal', oldVal)
}
)
return {
state }
}
}
</script>
vue3.2写法
<script setup>
import {
watch, reactive} from 'vue';
const state = reactive({
count1: 1,
count2: 2
});
const changCount = () => {
state.count1= state.count1* 2
state.count2= state.count2* 2
}
watch(state, (newVal, oldVal) => {
console.log(state.count1)
console.log(`watch监听变化前的数据:${
oldVal}`)
console.log(`watch监听变化后的数据:${
newVal}`)
},
{
immediate: true, // 立即执行
deep: true // 深度监听
})
watch(() => state.count2, (newVal, oldVal) => {
console.log(state.count1)
console.log(`watch监听变化前的数据:${
oldVal}`)
console.log(`watch监听变化后的数据:${
newVal}`)
})
</script>
- 监听一个对象下的变量,类似:
state.count2
,要写成watch(()=>state.count2,()=>{})
- 监听一个变量,可直接写
watch(count2,()=> {})
5 引入注册子组件
vue2.0写法
<script>
import child from './child.vue'
export default {
component: {
child
}
}
</script>
vue3.0写法
<script>
import child from './child.vue'
export default {
component: {
child
},
setup() {
.... }
}
</script>
vue3.2写法
<script setup>
import child from './child.vue'
</script>
vue3.2版本中,子组件主动注册,直接使用。
6 props父传子
vue2.0写法
- 父组件
<template>
<child :data="data"></child>
</template>
<script>
import child from './child.vue'
export default {
component: {
child },
data() {
return {
data: 1
}
}
}
</script>
- 子组件
<template>
<div>{
{
data }}</div>
</template>
<script>
export default {
// props: ['data']
props: {
data: {
type: Number,
required: true,
default: 2
}
}
}
</script>
vue3.0写法
- 父组件
<template>
<child :data="data"></child>
<template>
<script>
import {
ref } from 'vue'
import child from './child.vue'
component: {
child },
setup() {
const data = ref(1)
}
</script>
- 子组件
<template>
<div>{
{
data }}</div>
<template>
<script>
// props: ['data'],
props:{
// 基础类型指定
propA: Number,
// 指定多个类型
propB: [String, Number],
// 指定必传类型
propC: {
type: String,
required: true
},
// 带有默认值的数字
propD: {
type: Number,
default: 100
},
// 带有默认值的对象
propE: {
type: Object,
// 对象或数组默认值必须从一个工厂函数获取
default() {
return {
mes: 'lihua'}
}
},
// 自定义验证函数
propF: {
validator(value) {
return ['warning', 'success'].includes(value)
}
},
// 具有默认值的函数
prorG: {
type: Function,
default() {
return 'default function'
}
}
}
setup(props, content) {
console.log(props.data)
}
</script>
vue3.2写法
- 父组件
<template>
<child :data="data"></child>
</template>
<script setup>
import {
ref} from 'vue'
const data= ref(1)
</script>
- 子组件
<template>
<div>{
{
props.data}}</div>
<div>{
{
data}}</div>
</template>
<script setup>
import {
defineProps } from 'vue'
// const props = defineProps(['data'])
const props = defineProps({
data: {
type: Number,
default: 200
}
})
console.log(props.data)
</script>
7 emit子传父
vue2.0写法
- 父组件
<template>
<child @getData="dataToParent"></child>
</template>
<script>
export default {
getData(val) {
console.log(val)
}
}
</script>
- 子组件
<template>
<button @click="setData">按钮</button>
</template>
<script>
export default {
setData() {
this.$emit('dataToParent', 100)
}
}
</script>
vue3.0写法
- 父组件
<template>
<child @getData="dataToParent"></child>
</template>
<script>
export default {
setup() {
const getData = (val) => {
console.log(val)
}
}
}
</script>
- 子组件
<template>
<button @click="setData">按钮</button>
</template>
<script>
export default {
emits: ["dataToParent"],
setup(props, content) {
const setData = () => {
content.$emit('dataToParent', 100)
}
}
}
</script>
vue3.2写法
- 父组件
<template>
<child @setNum="getNum" @setStr="getStr"></child>
</template>
<script setup >
import child from './child.vue'
const getNum = val => {
console.log(val)
}
const getStr = val => {
console.log(val)
}
</script>
- 子组件
<template>
<button @click="setData(1)">按钮</button>
<button @click="setData(2)">按钮</button>
</template>
<script setup>
import {
defineEmits } from 'vue'
const emit = defineEmits(['setNum', 'setStr'])
const setData = type => {
if (type === 1) {
emit('setNum', 100)
} else {
emit('setStr', '测试数据')
}
}
</script>
8 ref变量和 defineExpose
vue2.0写法
<template>
<child ref="childRef"></child>
</template>
<script>
import child from './child.vue'
export default {
component: {
child },
mounted() {
// this.$refs.childRef
// 可以获取到子组件的变量和方法
}
}
</script>
vue3.0写法
- 父组件
<template>
<child ref="childRef"></child>
</template>
<script>
import child from './child.vue'
import {
ref, onMounted } from 'vue'
export default {
component: {
child },
setup() {
const childRef = ref(null)
onMounted(()=> {
console.log(childRef.value.addNum(1, 2))
// 如果子组件,没有主动向外暴露变量和方法,此时我们获取不到子组件上的信息
// 我们只能获取到子组件主动暴露的方法,通过defineExpose()主动暴露
})
}
}
</script>
- 子组件
<template>
<div>我是子组件</div>
</template>
<script>
export default {
setup() {
const addNum = (num1, num2) => {
return num1 + num2
}
return {
addNum }
}
}
</script>
vue3.2写法
- 父组件
<template>
<div>page3</div>
<child ref="childRef"></child>
</template>
<script setup>
import child from './child.vue'
import {
onMounted, ref } from 'vue'
const childRef = ref(null)
onMounted(() => {
console.log(childRef.value)
})
</script>
- 子组件
<template>
<div>我是子组件</div>
</template>
<script setup>
import {
onMounted, ref, defineExpose } from 'vue'
const addNum = (num1, num2) => {
return num1 + num2
}
const data = ref('测试数据')
const ownData = ref('我没暴露')
onMounted(() => {
console.log(addNum(1, 2))
console.log(data.value)
console.log(ownData.value)
})
defineExpose({
addNum, data })
</script>
9 useRoute和useRouter
vue2.0写法
<template>
<button @click="changePage">按钮</button>
</template>
<script>
export default {
changePage() {
this.$router.push({
path: '/page1', query: {
num: '100'} })
}
mounted() {
console.log(this.$route.query)
}
}
</script>
vue3.0写法
<template>
<div>page2</div>
<button @click="changePage">按钮</button>
</template>
<script>
import {
useRouter, useRoute } from 'vue-router'
import {
onMounted } from 'vue'
export default {
setup() {
const router = useRouter()
const route = useRoute()
const changePage = () => {
router.push({
path: '/page1', query: {
num: '33300' } })
}
onMounted(()=> {
console.log(route.query)
})
return {
changePage }
}
}
</script>
vue3.2写法
<template>
<button @click="changePage">按钮</button>
</template>
<script setup>
import {
useRouter, useRoute } from 'vue-router'
import {
onMounted } from 'vue'
cosnt router = useRouter()
const changePage = () => {
router.push({
path: '/page1', query: {
num: '100'} })
}
onMounted(()=> {
console.log(route.query)
})
</script>