Vue3
创建项目
// vite创建
npm init vue@latest
// 或
npm create vue@latest
// vue-cli创建
vue create demo
语法格式
Composition API (组合式)
<script setup>
// 导入函数
import { ref } from 'vue'
// 数据对象
const obj = ref({
sum: 5,
price: 10
})
// 事件函数
const btn = () => {
obj.value.sum = 10
}
</script>
新特性
Fragment :template 允许存在多个根标签
组合式API
setup
setup函数(狗都不用)
执行时机比beforeCreate钩子函数还要早
setup函数中获取不到this
数据和函数需要在 setup最后return才能在模板中使用
<script>
export default {
setup(){
const message = '你好'
const messageLog = () => {
console.log(message)
}
return {
message,
messageLog
}
}
}
</script>
<template>
<h1 @click='messageLog'>{{ message }}</h1>
</template>
setup语法糖(常用)
简化代码,不用return
<script setup>
const message = '你好'
const messageLog = () => {
console.log(message)
}
</script>
<template>
<h1 @click='messageLog'>{{ message }}</h1>
</template>
reactive函数
接受对象类型数据的参数传入,返回一个响应式对象
reactive只接受对象类型
<script setup>
import { reactive } from 'vue'
const state = reactive({
count:100
})
const setCount = () => {
state.count++
}
</script>
<template>
<h1 @click='setCount'>{{ state.count }}</h1>
</template>
ref函数
ref 可以构建《简单数据类型》《复杂数据类型》的响应性
如果要修改ref的响应性数据,必须通过.value进行访问
为什么要.value 因为proxy只能构建复杂数据类型,所以简单数据类型不能通过proxy处理代理对象
实际开发中常使用 ref 目的《让整个数据代码具备统一性》
当传入的数据是《简单数据类型》时,它的setter行为和getter行为本质上是函数的调用
当传入的数据是《复杂数据类型》时,它的响应性依赖于 reactive 响应性
<script setup>
// 导入函数
import { ref } from 'vue'
// 数据对象
const obj = ref({
sum: 5,
price: 10
})
// 数据对象
const count = ref(0)
// 访问数据需要.value
console.log(obj.value.sum)
console.log(count.value)
// 事件函数
const btn = () => {
obj.value.sum = 10
}
</script>
// 在页面不需要.value
<template>
<h1>{{ count }}</h1>
<h1>{{ obj.sum }}</h1>
</template>
computed 计算属性
// 基础写法
<script setup>
// 导入
import { ref, computed } from 'vue'
// 声明数据
const list = ref([1, 2, 3, 4, 5, 6])
// 计算属性
const computedList = computed(() => {
return list.value.filter(item => item > 2)
})
// 打印测试
console.log(computedList.value);
</script>
计算属性-可写
适用于全选反选
<script setup>
// 导入函数
import { ref, computed } from 'vue'
// 数据对象
const obj = ref({
sum: 5,
price: 10
})
// 事件函数
const btn = () => {
// 更改计算属性
num.value = 100
}
const num = computed({
// 依赖项发生改变会触发这个方法
get () {
return obj.value.sum * obj.value.price
},
// 计算属性的值被更改会触发这个方法
set (newValue) {
console.log(newValue) // 更改后的值
}
})
</script>
watch侦听器
watch(ref对象 , 事件函数 , 配置项)
<script setup>
// 导入函数
import { ref, watch } from 'vue'
// 数据对象
const obj = ref({
sum: 5,
price: 10
})
// 侦听数据
watch(obj, (newValue, oldValue) => {
console.log(newValue)
}, {
deep: true, // 深度侦听
immediate: true // 立即执行
})
</script>
仅侦听对象中的某个属性
watch(()=>对象.value.属性 , 事件函数 , 配置项)
<script setup>
// 导入函数
import { ref, watch } from 'vue'
// 数据对象
const obj = ref({
sum: 5,
price: 10
})
// 侦听数据
watch(()=>obj.value.sum, (newValue, oldValue) => {
console.log(newValue)
}, {
deep: true, // 深度侦听
immediate: true // 立即执行
})
</script>
侦听多个对象 [ref对象,ref对象]
watch([obj,obj], (newValue, oldValue) => {
console.log(newValue) // [obj,obj]
}, {
deep: true, // 深度侦听
immediate: true // 立即执行
})
生命周期
移除了两个生命周期函数,beforeCreate,Created
新增了一个,setup 可以把这个看做是created
修改了销毁的两个生命周期函数,改为 beforeUnmount , unmounted
setup
onBeforeMount onMounted
onBeforeUpdate onUpdated
onBeforeUnmount onUnmounted
// 使用
import { onMounted } from 'vue'
onMounted(() => {
console.log(`the component is now mounted.`)
})
ref获取dom
<div ref="but">{{ num }}</div>
1.声明一个数据 名字就叫要获取的ref名
const but = ref(null)
2.生命周期中获取
onMounted(() => {
console.log(but.value)
})
访问子组件里的属性及方法 (defineExpose )
获取子组件里的属性及方法需要子组件使用defineExpose 进行暴露,配合ref获取dom
// 子组件
<script setup>
import { ref,onMounted } from 'vue'
const num = ref(1)
const btn = () => {
console.log(num.value)
}
// 使用defineExpose 进行暴露
defineExpose({
num,
btn
})
</script>
// 父组件
<script setup>
import { ref,onMounted } from 'vue'
// 获取子组件dom
const but = ref(null)
onMounted(() => {
console.log(but.value) // 这里就有子组件里的属性和方法
})
</script>
<template>
<子组件 ref="but"></子组件>
</template>
父子组件通信
.sync 移除 v-model: 代替
子组件接收数据(defineProps)和返回数据(defineEmits)
// 导入 props 和 emit
import { defineProps, defineEmits } from 'vue'
// 接收数据
const props = defineProps({
数据名: {
type: 数据类型,
required: true // 是否必传
}
// 也可以这样接收
数据名:数据类型
})
// 打印测试
console.log(props.数据名)
// 返回数据 拿到父组件的 @自定义事件
const emits = defineEmits(['自定义事件名'])
// 触发方法
const onClick = () => {
emits('自定义事件名', 'a')
}
用 v-model 父子通信
// 父
<组件名 v-model:title="title" />
// 子
// 导入 props 和 emit
import { defineProps, defineEmits } from 'vue'
// 接收数据
const props = defineProps({
title: {
type: 数据类型,
required: true // 是否必传
}
})
// 返回数据 拿到父组件的自定义事件
const emits = defineEmits(['update:title'])
// 触发方法
const onClick = () => {
emits('update:title', 'a')
}
注册全局组件
src/libs/index.js
import Banner from './banner'
const libs = {
install (app) {
// app为vue的实例
// app.component('组件名',组件对象)
app.component('Banner', Banner)
}
}
export default libs
main.js
import libs from './libs/index'
createApp(App).use(libs)
全局过滤器
局部过滤器移除,全局过滤器用全局属性代替
// main.js文件内
// 全局属性 过滤器
const app = createApp(App)
// $filter 自定义的属性名 currencyUSD自定义的方法名
app.config.globalProperties.$filter = {
currencyUSD (value) {
return value
}
}
// main.js的这里要改成app
app.use(store).use(router).mount('#app')
使用
<div>{{ $filter.currencyUSD(num) }}</div>
跨层组件通信
父组件里有子组件,子组件里还有孙组件,孙组件里有重孙组件
父组件向下传值 , 单向传值
provide 传值
provide(‘自定义属性名’ , ‘传的值’)
inject 接收
inject(‘自定义属性名’)
// 父组件
<script setup>
// 导入
import { ref,provide } from 'vue'
// 定义数据
const age = ref(123)
// 传值
provide('age',age)
// 也可以传方法用来让孙组件来改传过去的值
provide('changeAge',(newValue)=>{ age.value = newValue})
</script>
// 某个孙组件
<script setup>
// 导入
import { inject } from 'vue'
// 接收
const age = inject('age') // 123 并且是响应式的
// 也可以接收方法用来改传过来的值
const changeAge = inject('changeAge')
// 某个方法里调用这个父传过来的方法
const btn = () => {
changeAge(100)
}
</script>
VUE 3.3 新特性
defineOptions
用来命名组件,解决某个组件起名为 index.vue 页面里第一行红色波浪线情况
类似于以下
<script>
export default {
name: 'LoginIndex'
}
</script>
使用方法
<script setup>
defineOptions({
name:'LoginIndex'
})
</script>
defineModel
用来简化v-model 相当于接收父传来的值使用并可以修改并同步到父
省略了props 和 emits
目前是试验阶段 需要配置才可生效
// vite.config.js
export default defineConfig({
plugins: [
// 这里需配置 true
vue({
defineModel:true
}),
],
})
使用
// 父组件
<script setup>
import { ref }from 'vue'
const txt = ref('100')
</script>
<template>
<子组件 v-model="txt"></子组件>
</template>
// 子组件
<script setup>
import { defineModel } from 'vue'
// 接收传下来的值
const txt = defineModel()
</script>
<template>
// 可以通过点击事件直接修改收到的值,并且父组件会同步,这里用input标签举例
<input type="text" :value="txt" @input= e => txt = e.target.value ></input>
</template>