创建项目 create-vue
create-vue 是 vue 官方新的脚手架工具,底层切换到了vite(下一代前端工具链),为开发提供极速响应
- 前提环境条件:已安装16.0或更高版本的node.js
- 创建vue应用
npm init vue@latest
指令将会安装并执行 create-vue
image.png
熟悉项目和关键文件
- package.json 项目包文件 核心依赖项变成了vue3.x和vite
- vite.config.js 项目配置文件 基于vite配置
- main.js 入口文件 createApp函数创建应用实例
// new Vue() 创建一个应用实例对象
import { createApp } from 'vue'
import App from './App.vue'//导入根组件
import './assets/main.css'//导入样式组件
// 1. 以App作为参数生成一个应用实例对象
// 2. 挂载到id为app的节点上(在index.html中)
createApp(App).mount('#app')
- App.vue 根组件 SFC单文件组件 script - template - style
- 脚本 script 和模板 template 顺序调整
- 模板 template 不再要求唯一根元素
- 脚本 script 添加 setup 标识支持组合式API
<!-- 开关:容许在script书写组合式API -->
<script setup>
...
</script>
<template>
<!-- 不再要求唯一根元素 -->
<header></header>
<main></main>
</template>
<style scoped>
</style>
- index.html 单页面入口提供id为app的挂载点
组合式API setup 选项
- 执行时机:beforeCreate 钩子之前 自动执行
- 定义数据/函数 然后以对象方式 return
- <script setup> 语法糖 经过语法糖的封装更简单的使用组合式API
- setup 中的 this 指向 undefined
<script>
export default{
setup(){
//数据
const message = '信息'
//函数
const logMessage = () => {
console.log(message)
}
return {
message,
logMessage
}
},
beforeCreate(){
}
}
</script>
<template>
{{ message }}
<button @click="logMessage"></button>
</template>
<script setup> 语法糖
<script setup>
export default{
const message = '信息'
//函数
const logMessage = () => {
console.log(message)
}
}
</script>
<template>
{{ message }}
<button @click="logMessage"></button>
</template>
reactive 和 ref 函数
- reactive 接收对象型数据的参数传入并返回一个响应式的对象
<script setup>
//导入
import { reactive, ref } from 'vue'
// 执行函数 传入对象类型参数 变量接收
const state = reactive({
count:0
})
const setCount = () => {
state.count ++
}
</script>
<template>
<div>
<button @click="setCount">{{ state.count }}}</button>
</div>
</template>
- ref 接收简单类型或者对象型数据的参数传入并返回一个响应式的对象
<script setup>
//导入
import { reactive, ref } from 'vue'
// 执行函数 传入简单/对象类型参数 变量接收
const count = ref(0)
const setCount = () => {
//脚本区域修改ref产生的响应式对象数据,必须通过.value 属性
count.value ++
}
</script>
<template>
<div>
<button @click="setCount">{{ count }}}</button>
</div>
</template>
- reactive VS ref
- reactive 不能处理简单类型数据
- ref 参数类型支持更好但是必须通过.value 访问修改
- ref 函数的内部实现依赖于reactive 函数
computed
基本思想与vue2.0 完全一致,组合式API下只是修改了写法
<script setup>
//导入
import { ref, computed } from 'vue'
const list = ref([1,2,3,4,5,6,7])
//执行函数 return 计算之后的值 变量接收
const computedList = computed(() => {
return list.value.filter(item => item > 2)
})
</script>
<template>
<div>
原始数据 {{ list }}
计算之后的值 {{ computedList }}
</div>
</template>
- 计算属性中不应该有“副作用”,比如异步请求/修改dom
- 避免直接修改计算属性的值,计算属性应该是只读的
watch 的基本使用和立即执行
用于 侦听一个或者多个数据的变化,数据变化时执行回调函数
两个额外参数: 1. immediate (立即执行) 2. deep (深度侦听)
侦听单个数据
<script setup>
//导入
import { ref, watch } from 'vue'
const count = ref(0)
const setCount = () => {
count.value ++
}
//ref 对象不需要加.value
watch(count,(newVal,oldVal)=> {
console.log(newVal,oldVal)
})
</script>
<template>
<button @click="setCount"></button>
</template>
侦听多个数据(同时侦听,不管哪个数据变化都需要执行回调)
<script setup>
//导入
import { ref, watch } from 'vue'
const count = ref(0)
const name = ref('肖战')
const setCount = () => {
count.value ++
}
const setName = () => {
name.value = '王一博'
}
//ref 对象不需要加.value
watch(
[count,name],
(
[newCount,newName],
[oldCount,oldName],
)=> {
console.log(newCount,newName,oldCount,oldName)
})
</script>
<template>
<button @click="setCount">修改count</button>
<button @click="setName">修改name</button>
</template>
immediate 立即执行, 在侦听器创建时立即出发回调,响应式数据变化之后继续执行回调
<script setup>
//导入
import { ref, watch } from 'vue'
const count = ref(0)
const setCount = () => {
count.value ++
}
//immediate 立即执行
watch(count,(newVal,oldVal)=> {
console.log(newVal,oldVal)
},{
immediate: true
})
</script>
<template>
<button @click="setCount">修改count</button>
</template>
watch 的深度监听和精确监听
deep 通过 watch 监听的ref对象默认是浅层侦听,直接修改嵌套的对象属性不会触发回调执行,需要开启deep选项
<script setup>
//导入
import { ref, watch } from 'vue'
const state = ref({count:0})
const setCount = () => {
state.value.count ++
}
//deep 深度侦听
watch(state,(newVal,oldVal)=> {
console.log(newVal,oldVal)
},{
deep: true
})
</script>
<template>
<button @click="setCount">修改count</button>
</template>
精确监听
<script setup>
//导入
import { ref, watch } from 'vue'
const state = ref({count:0,age:20})
const setCount = () => {
state.value.count ++
}
const setAge = () => {
state.value.age ++
}
//精确监听
// 1. 第一个回调函数 返回精确监听对象
// 2. 第二个回调函数 数据变化时执行的回调函数
watch(
() => state.value.count,
(newVal,oldVal) => {
console.log(newVal,oldVal)
}
)
</script>
<template>
<button @click="setCount">修改count</button>
<button @click="setAge">修改age</button>
</template>
考虑到 deep 性能损耗,尽量不开启deep
生命周期函数
image.png生命周期函数基本使用
- 导入生命周期函数
- 执行生命周期函数 传入回调
<script setup>
//导入
import { onMounted } from 'vue'
onMounted(() => {
//自定义逻辑
})
</script>
执行多次
生命周期函数是可以执行多次的,多次执行时传入的回调会在时机成熟时依次执行
父子通信—父传子 defineProps
父组件
<script setup>
import { ref } from 'vue'
// setup 语法糖下局部组件无需注册可以直接使用
import SonCom from './son-com.vue'
const count = ref('100')
</script>
<template>
<div class="father">
<!-- 1. 绑定属性 -->
<SonCom :message="count" />
</div>
</template>
子组件
<script setup>
// 2. defineProps 接收数据
const props = defineProps({
message: String,
})
</script>
<template>
<div class="son">
{{ props.message }}
</div>
</template>
父子通信—子传父 defineEmits
父级
<script setup>
// setup 语法糖下局部组件无需注册可以直接使用
import SonCom from './son-com.vue'
const getMessage = (msg) => {
console.log(msg);
}
</script>
<template>
<div class="father">
<!-- 1. 绑定事件 -->
<SonCom @get-message="getMessage" />
</div>
</template>
子级
<script setup>
// 2. 通过 defineEmits() -> emit(this.$emit)
const emit = defineEmits(['get-message'])
const sendMsg = () => {
//触发自定义事件 传递数据给父级
emit('get-message','子级数据')
}
</script>
<template>
<div class="son">
<button @click="sendMsg">触发自定义事件</button>
</div>
</template>
模板引用
通过 ref 标识 获取真实的 dom 对象或者组件实例对象
<script setup>
import { ref, onMounted } from 'vue'
import TestCom from './test-com.vue'
// 1. 调用 ref 函数 -> ref 对象
const h1Ref = ref(null)
const comRef = ref(null)
// 组件挂载完毕之后才能获取
onMounted(() => {
console.log(h1Ref.value)
console.log(comRef.value)
})
</script>
<template>
<div class="father">
<h1 ref="h1Ref">我的dom便签H1</h1>
<TestCom ref="comRef"></TestCom>
</div>
</template>
默认情况下,在<script setup>
语法糖下,组件内部的属性和方法是不开放给父组件访问的,可以通过defineExpose
编译宏指定哪些属性和方法允许访问
<script setup>
import { ref } from 'vue'
const name = ref('test name')
const setName = () => {
name.value = 'test new name'
}
//设置开放给父级使用的属性以及方法
defineExpose({
name,
setName
})
</script>
<template>
<div>
我的test组件
</div>
</template>
provide 和 inject
顶层组件向任意的底层组件 传递数据和方法,实现 跨层组件通信
- 顶层组件通过 provide 函数提供数据
- 底层组件通过 inject 函数获取数据
顶层组件代码
<script setup>
import { provide } from 'vue'
import son from './son.vue'
// 1. 顶层组件提供数据
provide('data-key','顶层组件数据')
</script>
<template>
<div>
<son></son>
</div>
</template>
底层组件代码
<script setup>
import { inject } from "vue";
// 2. 接收数据
const roomData = inject('data-key');
</script>
<template>
{{ roomDtata }}
</template>
顶层组件可以向底层组件传递方法,底层组件调用方法修改顶层组件中的数据
顶层组件代码
<script setup>
import { provide, ref } from 'vue'
import son from './son.vue'
import { count } from 'console';
const count = ref(0)
// 传递方法
const setCount = () => {
count.value ++
}
provide('setCount-key',setCount)
</script>
<template>
<div>
<son></son>
</div>
</template>
底层组件代码
<script setup>
import { inject } from "vue";
// 2. 接受数据
const setCount = inject('setCount-key');
</script>
<template>
<button @click="setCount"></button>
</template>
网友评论