vue3与vue2的区别
Vue 3在写法上与Vue 2有一些区别,以下是一些常见的区别:
引入方式:Vue 2使用Vue全局对象进行引入,而Vue 3使用createApp函数创建应用实例。
组件注册:Vue 2中使用Vue.component全局方法或在选项中使用components属性注册组件,而Vue 3中使用app.component方法进行组件注册。
模板语法:
Vue 2使用基于字符串的模板语法,例如<template>标签中的{{}}和v-指令。
Vue 3支持基于字符串的模板语法,但更推荐使用基于JSX的语法或使用<template>标签中的v-bind和v-on指令。
响应式数据:
Vue 2使用data选项定义响应式数据,需要使用this关键字来访问。
Vue 3中,使用setup函数来定义响应式数据,直接以函数的形式返回,并使用ref、reactive等函数进行包装,访问时无需使用this关键字。
生命周期钩子:Vue 3废弃了Vue 2中的一些生命周期钩子(如beforeCreate、beforeMount等),并引入了新的生命周期钩子(如onBeforeMount、onMounted等)。
插槽:Vue 2使用具名插槽和作用域插槽来实现组件之间的内容分发,而Vue 3引入了<slot>标签中的v-slot指令来代替Vue 2中的具名插槽和作用域插槽。
过滤器:Vue 2中可以使用过滤器对数据进行格式化处理,而Vue 3中移除了过滤器的概念,推荐使用计算属性或方法来处理数据格式化。
需要注意的是,虽然Vue 3在语法和用法上有一些变化,但它仍然保持了与Vue 2的高度兼容性,大部分Vue 2的代码可以迁移到Vue 3中,并且可以逐步采用Vue 3的新特性。
如果setup语法糖与普通的vue写法想一起用就写两个script标签。
<template>
<!-- Your template here -->
</template>
<script setup>
// Your setup function here
</script>
<script>
export default {
name: 'YourComponentName'
}
</script>
<style scoped>
/* Your styles here */
</style>
组合式API
与vue2的最大区别就是生命钩子函数,自定义变量与函数都可以在script标签中直接定义,但是:
变量接收ref函数的返回对象,更改时要用val.value="xxx"的方式进行更改。
对象要用reactive函数的返回对象。
与vue2中的自定义函数不一样,这里的自定义函数的this是undefine。
<template>
<div class="hello">
<h1>{{ xin }}</h1>
<h1>{{ obj.msg }}</h1>
<button @click="fun">按钮</button>
</div>
</template>
<script setup>
import { reactive, ref } from "vue";
const xin = ref("李义新");
const obj = reactive({
msg: "hello",
});
//这里的函数this是undefine
const fun = () => {
xin.value = "李义新655";
};
</script>
<style scoped></style>
路由
1、编写路由配置,src/router/router.js中。
2、创建与配置Vue Router实例,src/router/index.js中。
3、把路由配置到Vue,main.js中。
//router.js
import Register from '@/view/register.vue'
import Login from '@/view/login.vue'
const routes = [
{
name: 'login',
path: '/login',
component: Login
},
{
name: 'register',
path: '/register',
component: Register
}
];
export default routes
//index.js
//哈希模式,带#的
import { createRouter, createWebHashHistory } from 'vue-router';
import routes from './router'; // 导入 router 目录下的 router.js
const router = createRouter({
history: createWebHashHistory(),
routes
});
export default router;
//-------------------------------------------------------------------------
//历史模式,不带#的
import {createRouter, createWebHistory} from 'vue-router'
import routes from './router' // 导入 router 目录下的 router.js
const router = createRouter({
history: createWebHistory(process.env.BASE_URL),
routes
})
export default router;
//main.js
import { createApp } from 'vue'
import App from './App.vue'
import router from './router/index' // 加载 router 底下的 index.js 路由配置文件
const app = createApp(App)
app.use(router)
app.mount('#app')
全局方法与变量
Vue2中
定义全局方法与变量是写在new Vue之前。
使用时,在方法中this.Utils....;
Vue3中
定义全局方法与变量是写在创建App之前,在挂载app.aount*‘#app’)之后。
//定义时
const app = createApp(App);
app.config.globalProperties.Utils = Utils;
app.use(router)
app .mount('#app')
//其它组件使用时
import {getCurrentInstance} from "vue";
const {proxy} = getCurrentInstance(); //proxy是固定写法
const Utils = proxy.Utils;
父子组件的相互调用
父组件
<template>
<div :style="{backgroundColor: 'black', padding: '20px 0px',color:'white'}">
<Son ref="sonRef"
:msg="myMsg"
@opParent="parentMethod"
></Son>
<hr/>
<button @click="opSun">调用子组件</button>
<h2>父组件,子组件传过来的参数:{{sonMsg}}</h2>
</div>
</template>
<script setup>
import {ref} from 'vue'
import Son from "@/view/Son.vue";
const myMsg = ref("我是父组件传进来的参数");
//sonRef是Son的ref,名字一定要相同,用法很奇怪
const sonRef = ref();
//父组件调用子组件方法
const opSun = () => {
//通过ref调用子组件的方法,都必须子组件通过defineExpose去暴露一下
sonRef.value.ParentSon("666");
}
//用于介绍子组件传过来的参数
const sonMsg = ref("");
//子组件调用父组件的回调函数
const parentMethod = (e) => {
console.log(e);
sonMsg.value = e;
}
</script>
<style scoped>
</style>
子组件
<template>
<div :style="{background:'red',color:'white'}">
<div>子组件:我是父组件传入的参数:{{ msg }}</div>
<div>子组件:我是父组件调用子组件传入的参数:{{ msg2 }}</div>
<button @click="opParent">调用父组件</button>
</div>
</template>
<script setup>
import {ref, defineProps, defineExpose, defineEmits} from "vue"
const props = defineProps({
msg: {
type: String,
default: "www"
}
})
const msg2 = ref("");
const ParentSon = (parentMsg) => {
msg2.value = parentMsg;
}
const emit = defineEmits();
const opParent = () => {
emit("opParent", "我是子组件传过来的");
}
defineExpose({
ParentSon
})
</script>
<style scoped>
</style>
生命钩子
下述列表中没有 beforeCreate 和 created 的对应项。这是因为在Vue 3中,你不再需要这两个生命周期钩子,因为可以直接在 setup() 函数中执行这些生命周期钩子中的代码。
使用这些生命周期钩子的时候必须要从vue中引入。
beforeCreate => 无对应(在 setup() 开始之前运行)
created => 无对应(在 setup() 结束时运行)
beforeMount => onBeforeMount
mounted => onMounted
beforeUpdate => onBeforeUpdate
updated => onUpdated
beforeUnmount => onBeforeUnmount
unmounted => onUnmounted
errorCaptured => onErrorCaptured
renderTracked => onRenderTracked
renderTriggered => onRenderTriggered
这些生命周期钩子可以在Vue 3的 setup() 函数中
Vuex
vue3安装vuex
npm install vuex@next
创建store/index.js,用于配置vuex
import {createStore} from "vuex";
const store = createStore({
state() {
return {
count: 0
}
},
mutations: {
increment(state) {
state.count++;
}
}
})
export default store;
main.js
import {createApp} from 'vue'
import App from './App.vue'
import store from './store'
const app = createApp(App)
app.use(store)
app.mount('#app')
parent来使用vuex
<template>
<h2>{{ count }}</h2>
<button @click="increment">点击</button>
</template>
<script setup>
import {computed} from 'vue'
import {useStore} from 'vuex'
const store = useStore()
const count = computed(() => store.state.count)
const increment = () => {
store.commit('increment')
}
</script>