持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第4天,点击查看活动详情
技术更新很快,时代在推你进步,你却停滞不前,只会被时代淘汰。迫于内卷压力,再不学
vue3 真的感觉在跟时代划一道鸿沟。接下来让我们以最快的脚步认识vue3。
上一篇第一至第八点【传送门】
十. toRaw / markRaw
toRaw
返回 reactive 或 readonly 代理的原始对象。这是一个“逃生舱”,可用于临时读取数据而无需承担代理访问/跟踪的开销,也可用于写入数据而避免触发更改。不建议保留对原始对象的持久引用。请谨慎使用。
const foo = {};
const reactiveFoo = reactive(foo);
console.log(toRaw(reactiveFoo) === foo) // true
<script>
import { reactive, toRaw, isReactive } from 'vue'
export default {
name: 'HomeView',
setup () {
const person = reactive({
name: '小明',
age: 18,
likeFood: {
fruits: {
apple: '草莓'
}
}
});
const person2 = toRaw(person);
console.log(person)
console.log(person2)
console.log(isReactive(person))
console.log(isReactive(person2))
return {
}
},
}
</script>
markRaw
标记一个对象,使其永远不会转换为 proxy。返回对象本身。
<script>
import { reactive, markRaw, isReactive } from 'vue'
export default {
name: 'HomeView',
setup () {
let person = {
name: "小明",
age: 18
};
const markRawObj = markRaw(person); //标记person
const reactiveObj = reactive(markRawObj); //尝试转为响应式
console.log(isReactive(reactiveObj)) // false,说明未转成响应式
console.log(reactiveObj)
const obj = reactive({
name: "小风",
age: 19
})
console.log(obj)
return {};
}
}
</script>
十一. computed 计算属性
接受一个 getter 函数,并根据 getter 的返回值返回一个不可变的响应式 ref 对象。
<template>
<div>姓名:{{ name }}</div>
<div>年龄:{{ age }}</div>
<div>合并信息:{{ getInfo }}</div>
</template>
<script>
import { ref, computed } from "vue";
export default {
name: 'HomeView',
setup () {
let name = ref('小明')
let age = ref(21)
//计算属性
let getInfo = computed(() => {
return `${name.value},${age.value}`
})
getInfo.value += "尝试新增点东西"; //不允许修改,这里是非法的,修改不成功的
return {
name,
age,
getInfo,
}
}
}
</script>
或者,接受一个具有 get 和 set 函数的对象,用来创建可写的 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
十二. watch 监听
watch用法与vue2.x的差不多,watch(data,handler,object)。
- data:可以是返回值的getter函数,也可以是 ref。
- hander: 回调函数
- object: 可选配置项{ immediate : true, deep : true } //立即执行和深度监测
<template>
<ul>
<li
v-for="(item, index) in courseList"
:key="index"
@click="selectCourseFun(index)"
>
{{ item }}
</li>
</ul>
<div>默认课程:{{ defaultCourse }}</div>
<div>选中的课程:{{ selectCourse }}</div>
</template>
<script>
import { ref, reactive, toRefs, watch } from "vue";
export default {
name: 'HomeView',
setup () {
const defaultCourse = ref("javaScript进阶");
const data = reactive({
courseList: ["vue3初识", "Node.js进阶", "css世界"],
selectCourse: "",
selectCourseFun: (index) => {
data.selectCourse = data.courseList[index];
defaultCourse.value = data.courseList[index];
}
})
//监听单个
// watch(defaultCourse, (newValue, oldValue) => {
// console.log(`new--->${newValue}`);
// console.log(`old--->${oldValue}`);
// })
//监听多个
watch([defaultCourse, () => data.selectCourse], (newValue, oldValue) => {
console.log(`new--->${newValue}`);
console.log(`old--->${oldValue}`);
})
return {
defaultCourse,
...toRefs(data)
}
}
}
</script>
十三. watchEffect
立即执行传入的一个函数,同时响应式追踪其依赖,并在其依赖变更时重新运行该函数。
- 不需要手动传入依赖
- 每次初始化时会执行一次回调函数来自动获取依赖
- 无法获取到原值,只能得到变化后的值
<template>
<input type="text" v-model="name" />
</template>
<script>
import { reactive, toRefs, watchEffect } from "vue";
export default {
name: 'HomeView',
setup () {
let data = reactive({
name: "小明",
sex: "男",
});
watchEffect(() => {
console.log(data.name); //需要监听哪个就写哪个
});
return {
...toRefs(data),
};
}
}
</script>
十四. 注意事项
Vue.prototype 替换为 config.globalProperties
//vue2.x
//main.js
Vue.prototype.$test = "测试"
//页面xx.vue
let value = this.$test;
//vu3.x
//main.js
const app = createApp({});
app.config.globalProperties.$test = "测试"
//页面使用
<template>
<h1>{{ $test }}</h1> //直接使用
</template>
import { getCurrentInstance } from "vue";
export default {
setup(){
const { appContext } = getCurrentInstance();
console.log(appContext.config.globalProperties.$test) //可以通过这样获取
}
}
废弃 v-bind:title.sync 写法
//父组件
<ChildComponent :title.sync="pageTitle" /> //vue2.x写法
<ChildComponent v-model:title="pageTitle" /> //vue3.x写法
//子组件
<template>
<h1>{{ title }}</h1>
<button @click="changeTitle('newTitle')">Change</button>
</template>
<script>
import { defineComponent } from "vue";
export default defineComponent({
props: {
title: String
},
setup () {
function changeTitle (val) {
this.$emit("update:title", val)
}
return {
changeTitle
}
}
})
</script>
废弃 filter 过滤器
在 3.x 中,过滤器已移除,且不再支持。取而代之的是,我们建议用方法调用或计算属性来替换它们。
//父页组件
<template>
<child v-model:name="name" v-model:value="value"></child>
</template>
<script>
import { defineComponent, reactive, toRefs } from 'vue'
import child from "@/components/child";
export default defineComponent({
components: {
child
},
setup () {
let params = reactive({
name: "测试过滤功能",
value: 12.0124525721
})
return {
...toRefs(params)
}
}
})
</script>
//子组件
<template>
<h1>{{ name }}</h1>
<h2>{{ newValue }}</h2>
</template>
<script>
import { defineComponent, computed } from "vue";
export default defineComponent({
props: {
name: String,
value: Number,
},
setup (props) {
let newValue = computed(() => {
return Number(props.value.toFixed(2))
})
return {
newValue
}
}
})
</script>
使用全局方法实现过滤器
//main.js
const app = createApp(App);
app.config.globalProperties.$filters = {
exactTwoDecimal(val){
return Number(val.toFixed(2))
}
}
//页面
<template>
<h2>{{ $filters.exactTwoDecimal(value)}}</h2>
</template>