系列文章目录
文章目录
一、v-model 参数的用法
1、Vue2.x 的 .sync
在一个包含 title prop 的组件中,我们可以用以下方法表达对其赋新值的意图
普通写法:
this.$emit('update:title', newTitle)
<text-document
v-bind:title="doc.title"
v-on:update:title="doc.title = $event"
>
</text-document>
.sync
修饰符(简写):
<text-document v-bind:title.sync="doc.title"></text-document>
2、Vue3.x的 v-model:title=“xxx”
若要更改 model 名称,而不是更改组件内的 model 选项,那么可以将一个 arguments 传递给 model
<ChildComponent v-model:title="pageTitle"></ChildComponent>
<!-- 是以下的简写 -->
<ChildComponent :title="pageTitle" @update:title="pageTitle = $event"></ChildComponent>
示例:
index.vue 父组件
<template>
<p>{
{
name }} {
{
age }}</p>
<UserInfo
v-model:name="name"
v-model:age="age"
>
</UserInfo>
</template>
<script>
import {
reactive, toRefs } from 'vue'
import UserInfo from './UserInfo.vue';
export default {
name: 'VModel',
components: {
UserInfo},
setup() {
const state = reactive({
name: '杂货铺',
age: '20'
})
return toRefs(state)
}
};
</script>
UserInfo.vue 子组件
- v-bind 绑定属性的 value
- 监听 input 框内值的更新
<template>
<input :value="name" @input="$emit('update:name', $event.target.value)">
<input :value="age" @input="$emit('update:age', $event.target.value)">
</template>
<script>
export default {
name: 'UserInfo',
props: {
name: String,
age: String
}
};
</script>
二、watch 和 watchEffect 的区别
- 两者都可监听 data 属性变化
- watch 需要明确监听哪个属性
- watchEffect 会根据其中的属性,自动监听其变化
1、watch 监听(vue2.x)
(1)示例:watch 监听 值 的变化
- 第一个参数是要监听的属性
- 第二个参数是新旧值
- 第三个参数是初始化之前就监听(可选参数)
<template>
<p>watch vs watchEffect</p>
<p>{
{
numberRef }}</p>
</template>
<script>
import {
ref, toRefs, watch} from 'vue'
export default {
name: 'Watch',
setup() {
// 定义值类型
const numberRef = ref(100)
// watch 监听
watch(numberRef, (newNumber, oldNumber) => {
console.log('ref watch', newNumber, oldNumber);
})
// 定时器,修改 numberRef 的值,用于监听
setTimeout(() => {
numberRef.value = 200
}, 1000)
return {
numberRef,
}
}
};
</script>
watch 监听可选的第三个参数
immediate: true // 初始化之前就监听,可选
(2)示例:watch 监听 对象 的变化
<template>
<p>watch vs watchEffect</p>
<p>{
{
name }} {
{
age }}</p>
</template>
<script>
import {
reactive, toRefs, watch} from 'vue'
export default {
name: 'Watch',
setup() {
const state = reactive({
name: '杂货铺',
age: 21
})
watch(
// 第一个参数,确定要监听哪个属性
() => state.age,
// 第二个参数,回调函数
(newAge, oldAge) => {
console.log('state watch', newAge, oldAge);
},
// 第三个参数,配置项,可选
{
immediate: true, // 初始换之前就监听,可选
deep: true // 深度监听
}
)
setTimeout(() => {
state.age = 25
}, 3000)
setTimeout(() => {
state.name = '前端杂货铺'
}, 5000)
return {
...toRefs(state)
}
}
};
</script>
2、watchEffect 监听(Vue3.x)
示例:watchEffect 监听对象变化
<template>
<p>watch vs watchEffect</p>
<p>{
{
name }} {
{
age }}</p>
</template>
<script>
import {
reactive, toRefs, watchEffect} from 'vue'
export default {
name: 'Watch',
setup() {
const state = reactive({
name: '杂货铺',
age: 21
})
// 初始化时,一定会执行一次(收集要监听的数据)
watchEffect(() => {
console.log('hello watchEffect');
})
// 监听 state.name
watchEffect(() => {
console.log('state.name', state.name);
})
// 监听 state.age
watchEffect(() => {
console.log('state.age', state.age);
})
setTimeout(() => {
state.age = 25
}, 1500)
setTimeout(() => {
state.name = '前端杂货铺'
}, 3000)
return {
...toRefs(state)
}
}
};
</script>
3、watch 和 watchEffect 的区别
- 两者都可监听 data 属性变化
- watch 需要明确监听哪个属性
- watchEffect 会根据其中的属性,自动监听其变化
三、在 setup 中如何获取组件实例
- 在 setup 和其他 Composition API 中没有 this
- 可通过 getCurrentInstance 获取当前实例
- 若使用 Options API 可照常使用 this
示例:使用 getCurrentInstance 获取当前实例
<template>
<p>setup中获取组件实例</p>
</template>
<script>
import {
getCurrentInstance, onMounted } from 'vue';
export default {
name: 'GetInstance',
data() {
return {
x: 1
}
},
setup() {
// Composition API 没有 this => undefined
console.log('this1', this);
// 获取当前实例
const instance = getCurrentInstance()
console.log('instance', instance);
// 挂载完成 => 通过 instance.data.x 获取 x 的值
onMounted(() => {
// 挂载完也没有 this => undefined
console.log('this in onMounted', this);
console.log('x', instance.data.x);
})
},
// vue2.x 中有 this,能直接取到值
mounted() {
console.log('this2', this);
console.log('x', this.x);
}
};
</script>
四、Vue3 为何比 Vue2 快
- Proxy 响应式
- PatchFlag
- hoistStatic
- cacheHandler
- SRR 优化
- tree-shaking
1、PatchFlag
- 编译模板时,动态节点做标记
- 标记,分为不同的类型,如 TEXT PROPS
- diff 算法时,可以区分静态节点,以及不同类型的动态节点
测试地址:PatchFlag测试
Vue2.x 与 Vue3.x diff 算法的部分区别:
出处:https://coding.imooc.com/lesson/419.html#mid=41996
2、hoistStatic
- 将静态节点的定义,提升到父作用域,缓存起来
- 多个相邻的静态节点,会被合并起来
- 典型的拿空间换时间的优化策略
Options 打开 hoistStatic:
3、cacheHandler
- 缓存事件
4、SSR 优化
- 静态节点直接输出,绕过了 vdom
- 动态节点,还是需要动态渲染
5、tree shaking
- 编译时,根据不同的情况,引入不同的 API
需要什么就引入什么:
五、Vite 为何启动快?
- 开发环境使用 ES6 Module,无需打包 —— 非常快
- 生产环境使用 rollup,并不会快很多
示例:ES Module 在浏览器中的使用
print.js 文件
export default function (a, b) {
console.log(a, b)
}
add.js 文件
import print from './print.js'
export default function add(a, b) {
print('print', 'add')
return a + b
}
test.html
- script 标签中要使用
type="module"
- 导入所需文件
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>ES Module demo</title>
</head>
<body>
<p>基本演示</p>
<script type="module">
import add from './src/add.js'
const res = add(1, 2)
console.log('add res', res)
</script>
</body>
</html>
六、Composition API 和 React Hooks 对比
- 前者 setup 只会被调用一次,而后者函数会被多次调用
- 前者无需 useMemo useCallback,因为 setup 只调用一次
- 前者无需顾虑调用顺序,而后者需要保证 hooks 的顺序一致
不积跬步无以至千里 不积小流无以成江海
点个专注不迷路,持续更新中…