一、setup 选项
<script>
export default {/*** 1、setup 执行时机早于 beforeCreate* 2、setup 中无法获取 this* 3、数据和函数需要在 setup 最后 return,才能在模板中使用* 4、可以通过 setup 语法糖简化代码*/setup(){// console.log('setup function', this)// 数据const msg = 'Hello Vue3'const logMsg = () => {console.log(msg)}return{msg,logMsg}},beforeCreate(){// console.log('beforeCreate function')}
}
</script>
若未 return 在浏览器也会有警告
每次都需要 return,若数据与函数的量很大,就会很麻烦,所以可以通过语法糖来简化代码
<script setup>
const msg = 'Hello Vue3'
const logMsg = () => {console.log(msg)
}
</script><template><div>{{ msg }}</div><button @click="logMsg"></button>
</template>
二、reactive 和 ref 函数
reactive()
:接收对象类型数据的参数传入并返回一个响应式的对象
步骤:
-
从 vue 中导入 reactive 函数
-
在
<script setup>
中执行 reactive 函数并传入类型为对象的初始值,并使用变量接收返回值
<script setup>import { reactive } from 'vue'const state = reactive({count: 100})const setCount = () => {state.count++;}
</script><template><div><!-- <div>{{ state.count }}</div><button @click="setCount">+1</button> --></div>
</template>
ref()
:接收简单类型或对象类型的数据传入并返回一个响应式的对象底层是将简单类型数据包装成对象类型的数据,然后借助
reactive
实现响应式
步骤:
-
从 vue 中导入 ref函数
-
在
<script setup>
中执行 ref函数并传入类型为对象的初始值,并使用变量接收返回值
<script setup>
import { ref } from 'vue'const count = ref(0)
const setCount = () => {// 访问数据需要通过 .value【template中不需要】count.value++;
}
</script><template><div><div>{{ count }}</div><button @click="setCount">+1</button></div>
</template>
三、computed
步骤:
-
导入
computed
函数 -
执行函数在回调函数中 return 基于响应式数据做计算的值,用变量接收
<script setup>
import { computed, ref } from 'vue'const list = ref([1, 2, 3, 4, 5, 6, 7, 8])const computedList = computed(() => {// 只读return list.value.filter(item => item > 2)
})const addFn = () => {list.value.push(9)
}
</script><template><div><div>原始数据:{{ list }}</div><div>计算后数据:{{ computedList }}</div><button @click="addFn">修改</button></div>
</template>
以上创建的是一个 只读 的计算属性 ref,若要创建一个 可写 的计算属性 ref,可以这样做:
const count = ref(1)
const plusOne = computed({get: () => count.value + 1,set: (val) => {count.value = val - 1}
})plusOne.value = 1
console.log(count.value) // 0
在计算属性中不要进行异步请求或这修改 DOM 的操作
避免直接修改计算属性的值
四、watch
侦听一个或者多个数据的变化,数据变化时执行回调函数
<script setup>
import { ref, watch } from 'vue'
const count = ref(0)
const name = ref('cp')const setCount = () => {count.value++;
}const setName = () => {name.value = '张三 - 李四'
}// 侦听单个数据
watch(count, (newValue, oldValue) => {console.log(`count 值发生了变化,新值为 ${newValue},旧值为 ${oldValue}`)
})
// 侦听多个数据
watch([count, name],([newCount, newNode], [oldCount, oldName]) => {console.log('count 或 name 发生了变化', [newCount, newNode], [oldCount, oldName])
})
</script><template><div>{{ count }}</div><button @click="setCount">改数字</button><div>{{ name }}</div><button @click="setName">改名字</button>
</template>
两个参数:
immediate
(立即执行)
deep
(深度侦听)
watch(count, ()=>{console.log('count变了')
},{immediate: true
})
watch 可以直接监视简单类型数据
const ref = ref(简单类型)
watch 无法监视复杂类型内部数据的变化
const ref = ref(复杂类型)
watch(复杂类型对象, (newValue) => {console.log(newValue);
}, {deep: true
})
若没有添加 deep 参数,默认的是监听对象的地址是否变化,除非修改了对象的地址,否则不会被监听到。
若要监听复杂类型对象内部属性的变化,则需要添加 deep 参数,即可对其进行监听
精确监听对象的某个属性
在不开启 deep 的前提下,侦听对象属性的变化,只有属性变化时才执行回调
// 精确侦听某个属性
const info = ref({name: 'cp',age: 18
})
watch(() => info.value.age,() => console.log('age变了')
)
五、生命周期函数
选项式 API | 组合式 API |
---|---|
beforeCreate/ created | setup |
beforeMount | onBeforeMount |
mounted | onMounted |
beforeUpdate | onBreforeUpdate |
update | onUpdate |
beforeUnmount | onBeforeUnmount |
unmounted | onUnmounted |
<script setup>
import { onMounted } from "vue"// 一进入页面就调用
const getList = () => {setTimeout(() => {console.log('发送请求,获取列表数据')}, 2000)
}
getList()// 在 mounted 时执行
onMounted(() => {console.log('mounted 生命周期函数 - 逻辑1')
})
// 写成函数的调用方式,可以调用多次,并不会冲突,而是按照顺序依次执行
onMounted(() => {console.log('mounted 生命周期函数 - 逻辑2')
})
</script>
六、父子通信
1、父传子
基本思想:
父组件给子组件绑定属性
子组件内部通过
props
选项接收
defineProps
原理:编译阶段的一个标识,实际编译器解析时,遇到后会进行编译转换
2、子传父
基本思想:
父组件中给子组件标签通过
@绑定事件
子组件内部通过
emit
方法触发事件
七、模板引用
通过
ref
标识获取真实的 DOM 对象或者组件实例对象
步骤:
-
调用 ref 函数生成一个 ref 对象
-
通过 ref 标识绑定 ref 对象到
<script setup>
import { ref } from 'vue'
// 通过 ref 函数获得一个 ref 对象
const h1Ref = ref(null)
</script><template><!-- 通过 ref 标识绑定 ref 对象 --><h1 ref="h1Ref">我是 DOM 标签 h1</h1>
</template>
获取模板引用的时机:组件挂载完毕
默认情况下在 <script setup>
语法糖下组件内部的属性和方法是不开放给父组件访问的,可以通过 defineExpose
编译宏指定哪些属性和方法允许访问
<script setup>
import { ref } from 'vue'
const testMsg = ref('this is test msg')
defineExpose({testMsg
})
</script>
八、provide 和 inject
作用:顶层组件向任意的底层组件传递数据和方法,实现跨层组件通信
跨层传递普通数据
-
顶层组件通过
provide
函数提供数据 -
底层组件通过
inject
函数获取数据
// 顶层组件
provide('key', 顶层组件中的数据)// 底层组件
const msg = inject('key')
顶层组件可以向子层组件传递方法,底层组件调用方法修改顶层组件中的数据【实际在修改数据的依然是顶层组件】
一 叶 知 秋,奥 妙 玄 心