vue3 之 问题总结(一)
Vue3 官网:https://cn.vuejs.org/guide/introduction.html
一、为什么要使用ref?
使用ref来创建响应式数据,当你在模板中使用了一个 ref,然后改变了这个 ref 的值时,Vue 会自动检测到这个变化,并且相应地更新 DOM。在标准的 JavaScript 中,检测普通变量的访问或修改是行不通的。然而,我们可以通过 getter 和 setter 方法来拦截对象属性的 get 和 set 操作。该 .value 属性给予了 Vue 一个机会来检测 ref 何时被访问或修改。
【那这儿就要提到其原理】
Vue3是通过Object.define.proxy 对对象进行代理,从而实现数据劫持。使用Proxy 的好处是它可以完美的监听到任何方式的数据改变,唯一的缺点是兼容性的问题,因为 Proxy 是 ES6 的语法
Vue3.0 摒弃了 Object.defineProperty,改成了 Proxy 。
首先说一下 Object.defineProperty 的缺点:
① Object.defineProperty 无法监控到数组下标的变化,导致直接通过数组的下标给数组设置值,不能实施响应。 this.$set()解决
② Object.defineProperty 只能劫持对象的属性,因此我们需要对每个对象的每个属性进行遍历。Vue2.X 里,是通过递归 + 遍历 data 对象来实现对数据的监控的,如果属性值也是对象那么需要深度遍历,显然如果能劫持一个完整的对象才是更好的选择。
③ proxy:可以代理整个对象,并返回一个新对象,而Object.defineProperty代理的是对象中的单个属性
二、自动引入ref、reactive等等
可以使用 unplugin-auto-import 插件
npm i unplugin-auto-import -D
vite中使用 ,于vite.config.js中配置
import vue from '@vitejs/plugin-vue';
// 引入插件
import AutoImport from 'unplugin-auto-import/vite';
export default defineConfig({
plugins: [
vue(),
AutoImport({
imports:['vue','vue-router']
})
]
});
三、reactive() 的局限性
① 有限的值类型:只能用于对象类型(对象、数组这样的集合类型)
② 不能替换整个对象:如果“替换”,那么可能导致数据失去响应式
③ 对解构操作不友好:会导致数据失去响应式
四、reactive、ref 与 shallowRef的区别
① ref:可以定义基本类型和赋值类型
② reactive只能定义复杂类型,定义基本类型会有警告,而且数据不具备响应式
③ shallowRef的性能高于ref,复杂类型的完整赋值,shallowRef只需要解包一次,ref需要解包两次
④ ref定义的变量获取时需要.value,reactive可以直接获取
五、如何修改计算属性呢
计算属性默认是只读的。当你尝试修改一个计算属性时,你会收到一个运行时警告。只在某些特殊场景中你可能才需要用到“可写”的属性,你可以通过同时提供 getter 和 setter 来创建:
<script setup>
import { ref, computed } from 'vue'
const firstName = ref('John')
const lastName = ref('Doe')
const fullName = computed({
// getter
get() {
return firstName.value + ' ' + lastName.value
},
// setter
set(newValue) {
// 注意:我们这里使用的是解构赋值语法
[firstName.value, lastName.value] = newValue.split(' ')
}
})
</script>
六、聊聊v-if、v-for、v-show吧
最主要是来说说 v-if与v-for v-if与v-show
① v-if 与 v-for
1) vue2 v-for 优先级高于 v-if ; vue3 v-if 优先级高于 v-for
2) 两者不推荐同时使用
② v-if 与 v-show
1) v-if 是控制标签/元素的销毁和重建
2) v-show 是相当于display属性值来隐藏和显示
七、简单聊聊vue3的组件通信吧
1)父传子
通过在子组件上定义自定义属性进行传递,在子组件中使用defineProps进行接收(不携带默认值),如果需要携带默认值则使用withDefaults(defineProps(),{默认值})进行接收
<Child :msg="msg" num="152" @zxc="zxc"></Child>
// 父传子
type Props = {
num: number,
msg: string,
str: string
}
// 不带默认值的写法
// let props = defineProps<Props>()
// 携带默认值
let props = withDefaults(defineProps<Props>(), {
str: '默认值'
})
2)子传父
子组件自定义事件进行触发,通过defineEmits来触发事件,父组件通过自定义事件接收
<button @click="devFather">子传父</button>
// 子传父
let childMsg = ref<string>('子组件的数据')
type Emit = {
(event: 'zaq'): void
(event: 'zxc', childMsg: string): void
}
let $emit = defineEmits<Emit>()
let devFather = () => {
// 子传父,不携带参数
// $emit('zaq')
// 携带参数
$emit('zxc', childMsg.value)
}
注:该文档为个人理解所写,有误可建议修改

浙公网安备 33010602011771号