安装
一、首先全局安装vue脚手架
npm i @vue/cli -g
二、创建项目
vue create 项目名称
三、进行vue3项目配置
四、安装完成
vue3的介绍
vue3特点
- 按需加载
- 新增组合式api
- 更加接近原生js
- 无需构建步骤,渐进式增强静态的 HTML
- 在任何页面中作为 Web Components 嵌入
- 单页应用 (SPA)
- 全栈 / 服务端渲染 (SSR) - Jamstack / 静态站点生成 (SSG)
- 开发桌面端、移动端、WebGL,甚至是命令行终端中的界面
vscode插件推荐
- vue2中需要安装插件
vetur
,可以实现组件高亮。但是vue3的一些语法在vetur中报错。 - vue3中需要安装插件
volar
,提供了更加强大的功能。Vue Volar extension Pack
vue2与vue3的不同点
一、启动方式
- 在vue2中
import Vue from 'vue'
new Vue({
store,
router,
render:h=>h(App)
}).$mount("#app")
- 在vue3中
import {createApp} from 'vue'
createApp(App).use(router).use(store).mount("#app")
二、在main.js中的引入
- 应用实例并不只限于一个。createApp API 允许你在同一个页面中创建多个共存的 Vue 应用,而且每个应用都拥有自己的用于配置和全局资源的作用域。
- vue2中我们可以使用pototype(原型)的形式去进行操作,引入的是构造函数
- vue3中需要使用结构的形式进行操作,引入的是工厂函数
- vue3中app组件中可以没有根标签
//引入的不再是Vue构造函数了,引入的是一个名为createApp的工厂函数
import {createApp} from 'vue
import App from './App.vue
//创建应用实例对象-app(类似于之前vue2中的vm实例,但是app比vm更轻)
createApp(APP).mount('#app')
createApp(App).use(router).use(store).mount("#app")
- 全局方法挂载
- v3中
app.config.globalProperties.$say = function(msg){alert(msg)}
- v2中
Vue.prototype.$say = function(msg){alert(msg)}
- v3中
- 根节点
v3 可以有多个根节点
v2 只能有一个根节点
生命周期
- vue3中的生命周期函数,可以按需导入到组件中,且只能在 setup() 函数中使用
- setup的生命周期需要加on前缀
- vue3相对于vue2的改变
- beforeDestroy 改名为 beforeUnmount
- destroyed 改名为 unmounted
- beforeCreate => setup
- created => setup
- beforeMount => onBeforeMount
- mounted => onMounted
- beforeUpdate => onBeforeUpdate
- updated => onUpdated
- beforeUnmount => onBeforeUnmount
- unmounted => onUnmounted
语法
<script>
import { onMounted, onUpdated, onUnmounted } from 'vue';
export default {
setup() { //在组件挂载前执行
onMounted(() => {
console.log('mounted!');
});
onUpdated(() => {
console.log('updated!');
});
onUnmounted(() => { //组件已经卸载
console.log('unmounted!');
});
return {};
}
};
</script>
setup语法糖
- 直接在script标签中添加setup属性就可以直接使用setup语法糖了。
- 使用setup语法糖后,不用写setup函数;组件只需要引入不需要注册;属性和方法也不需要再返回,可以直接在template模板中使用。
<template>
<my-component :num="num" @click="addNum" />
</template>
<script setup>
import { ref } from 'vue';
import MyComponent from './MyComponent .vue';
// 像在平常的setup中一样的写,但是不需要返回任何变量
const num= ref(0) //在此处定义的 num 可以直接使用
const addNum= () => { //函数也可以直接引用,不用在return中返回
num.value++
}
</script>
-
setup语法糖中新增的api
defineProps
:子组件接收父组件中传来的propsdefineEmits
:子组件调用父组件中的方法defineExpose
:子组件暴露属性,可以在父组件中拿到
setup组件
-
setup() 函数在组件创建 created() 之前执行。
-
setup() 函数接收两个参数 props 和 context。
-
第一个参数 props,它是响应式的,当传入新的 prop 时,它将被更新。
-
第二个参数 context 是一个普通的 JavaScript 对象,它是一个上下文对象,暴露了其它可能在 setup 中有用的值。
-
注意:在 setup 中你应该避免使用 this,因为它不会找到组件实例。setup 的调用发生在 data property、computed property 或 methods 被解析之前,所以它们无法在 setup 中被获取。
ref和reactive
-
reactive()负责复杂的数据结构,ref()则可以把基本的数据结构包装成响应式
-
ref()函数接收一个参数值,返回一个响应式的数据对象。该对象只包含一个指向内部值的 .value 属性
-
ref()接收一个泛型来定义他的类型
-
reactive()函数接收一个普通对象,返回该普通对象的响应式代理对象
-
reactive()接收一个泛型来定义他的类型
-
ref定义的是基本数据类型
-
ref通过Object.defineProperty()的get和set实现数据劫持
-
ref操作数据.value,读取时不需要。value
-
reactive定义对象或数组数据类型
-
reactive通过Proxy实现数据劫持
-
reactive操作和读取数据不需要.value
<button @click="num++">{{num}}</button>
<button @click="setNum(num+5)">加5</button>
<p v-for="item in list" :key="item">{{item}}</p>
<input type="text" v-model="temp" @keyup.enter="addList()">
</div>
</template>
<script>
// ref 导入一个创建响应式 值类型数据的方法
// reactive 响应式 引用类型方法
import {ref,reactive} from 'vue'
export default {
setup(){
// 创造一个响应式对象 num 默认值是5
const num = ref(5);
// 定义更新num的方法
function setNum(n){
// 在setup 中num的值访问与赋值要加value 在template不需要
num.value = n;
}
// 返回num
// 定义一个响应式列表数据
var list = reactive(["Vue","react","Angular","小程序"])
// 定义temp 临时数据
var temp = ref("");
// 定义添加list 的方法,追加数据
function addList(){
// 注意值类型访问要加value
list.push(temp.value);
temp.value = "";
}
// 返回 定义的方法与数据
return {num,setNum,list,temp,addList};
},
beforeUnmount(){
console.log("组件将要卸载")
},
unmounted(){
console.log("组件已经卸载")
}
}
dfineProps 定义父组件的传参props
<template>
<span>
<button @click="count--">-</button>
<input type="text" style="width:90px" v-model="count">
<button @click="count++">+</button>
</span>
</template>
<script setup>
// dfineProps 定义props
import {defineProps,ref,watch,defineEmits,watchEffect,defineExpose} from 'vue'
// 定义props传入参数
const props= defineProps({
// 类型为数字或者字符串,默认值为1
value:{type:[Number,String],default:1}
})
// 定义一个响应式对象初始值为 props.value
const count = ref(props.value)
defineEmits和defineExpose
子组件
<template>
<span>
<button @click="count--">-</button>
<input type="text" style="width:90px" v-model="count">
<button @click="count++">+</button>
</span>
</template>
<script setup>
// dfineProps 定义props
import {defineProps,ref,watch,defineEmits,watchEffect,defineExpose} from 'vue'
// 定义props传入参数
const props= defineProps({
// 类型为数字或者字符串,默认值为1
value:{type:[Number,String],default:1}
})
// 定义一个响应式对象初始值为 props.value
const count = ref(props.value)
// 定义事件发送器
var emits = defineEmits(["input"])
// 监听count的变化
watch(count,()=>{
// 发送一个input事件 事件的值为count的value
emits("input",count.value)
})
// 在watchEffect都会被自动监听,执行局回调函数
// 只要watchEffect中出现了数据,数据发生变化时候,
// 都会执行watchEffect
watchEffect(()=>{
count.value = props.value;
})
// defineExpose 规定了组件那些值可以被引用获取
defineExpose({count})
</script>
父组件
<template>
<div>
<h1>setup</h1>
<button @click="num++">{{num}}</button> <br>
<stepper-com :value="num" @input="num=$event" ref="stepper"></stepper-com>
<p>{{size}}</p>
</div>
</template>
<script setup>
// 使用setup 可以简写(不用导出,组件不用注册了)
import StepperCom from '@/components/StepperCom.vue'
// 导入useWinSize方法
import {useWinSize} from '@/utils/utils.js'
import {ref,onMounted} from 'vue';
const num = ref(5);
const stepper = ref();
onMounted(() => {
console.log("组件已经挂载完毕")
// 组件挂载完毕引用steper组件
// stepper.value就是对stepper-com 组件的引用
console.log(stepper.value.count)
})
// 返回执行返回一个对象size
const size = useWinSize();
</script>