跳转到内容

基础 API 使用

router

js
import { useRouter } from 'vue-router';
const router = useRouter();
const test = () => {
	router.push('/');
};

路由传参

javascript
router.push({
	path: '/weather_desc',
	query: { id: item.warnId },
});

router.push({
	name: 'WeatherDesc',
	params: { id: item.warnId },
});

获取路由参数

js
import { useRoute } from 'vue-router';
const route = useRoute();
// 获取query 参数
const rank = route.query.rank;
// 获取 params 参数
const rank = route.params.rank;

第二种获取params

js
{
  path: '/survey/medal/:rank',   // 动态路由段
  name: 'SurveyMedal',
  component: () => import('@/views/Medal.vue')
}

// 跳转的时候
router.push({
  name: 'SurveyMedal',
  params: { rank: res.data }
})

route

js
import { useRoute } from 'vue-router';
const route = useRoute();
// 当前路由的地址,不包含参数、hash
const path = route.path;
// 包含参数、hash
const fullPath = route.fullPath;
// 获取query 参数
const rank = route.query.rank;
// 获取 params 参数
const rank = route.params.rank;

watchEffect

立即运行一个函数,同时响应式地追踪其依赖,并在依赖更改时重新执行

优点: 监听多个依赖项,不需要指定监听源,可以消除手动维护依赖列表的负担

WARNING

注意:如果异步创建了监听器,则不会自动关闭,需要手动销毁否则造成内存泄露

js
import { watchEffect, watchPostEffect, onUnmounted } from 'vue';

const unWatchEffect = watchEffect(async () => {}, {
	flush: 'post', // 如何想在回调中访问被Vue更新之后的Dom
});

watchPostEffect(() => {
	/* 在 Vue 更新后执行 */
});

// 手动销毁
onUnmounted(() => {
	unWatchEffect();
});

watch

对单一依赖进行监听

js
import { watch, useRoute } from 'vue';
const route = useRoute();
watch(
	() => route,
	(newRoute) => {
		// ...
	},
	{ deep: true, immediate: true }
);
// 监听一个ref
const visible = ref(false);
watch(visible, (newValue) => {});

customRef

自定义 ref 增强

js
import { customRef } from 'vue';

/**
 * 全局loading变量,多个请求保持loading状态,而不会在1个请求结束后关闭loading
 */
export const loading = customRef((track, trigger) => {
	let loadingCount = 0;
	return {
		// loading.value会触发get
		get() {
			track(); // 收集哪些地方调用了这个依赖,后续通知更新
			// loadingCount为0自动关闭loading状态
			return loadingCount > 0;
		},
		set(value) {
			// 如果loading设置为true就+1否则-1
			loadingCount += value ? 1 : -1;
			loadingCount = Math.max(0, loadingCount); // 处理边界,如果小于0就赋值为0
			console.log(loadingCount);
			trigger(); // 通知更新
		},
	};
});

reactive

响应式对象,用于复杂数据处理。数组、对象等

js
import { reactive } from 'vue';
const arr = reactive([1, 2, 3]);

// 直接赋值不会触发响应式
arr = [4, 5, 6];
// 则需要操作数组
arr[0] = 4;
arr[1] = 5;
arr[2] = 6;

teleport

专门用于将模板中的某部分 DOM 移动到其他容器

vue
<template>
	<teleport to="body">
		<div class="modal-backdrop" v-if="visible">
			<div class="modal">
				<slot />
			</div>
		</div>
	</teleport>
</template>
<!-- 或者 -->
<template>
	<teleport to="#id">
		<div class="modal-backdrop" v-if="visible">
			<div class="modal">
				<slot />
			</div>
		</div>
	</teleport>
</template>

provide/inject

用于跨组件层级传递数据,避免 props 逐级传递(prop drilling) provide 提供数据,inject 注入数据,适用于组件树中深层次组件通信

WARNING

注意:默认非响应式,需要使用 ref 或 reactive 包装以保持响应性

js
// 父组件 (提供数据)
import { provide, ref, reactive, readonly } from 'vue';

// 非响应式值
provide('staticMessage', '这是一个静态消息');

// 响应式值
const count = ref(0);
provide('counter', count); // 直接提供ref,保持响应性

// 提供修改方法,避免子组件直接修改状态
provide('incrementCount', () => {
	count.value++;
});

// 对象写法:使用Symbol作为注入键,避免命名冲突
const userSymbol = Symbol('user');
const userState = reactive({
	name: '张三',
	age: 25,
	role: 'admin',
});

// 使用readonly包装,防止子组件修改状态
provide(userSymbol, readonly(userState));

// 提供修改方法
provide('updateUser', (newName) => {
	userState.name = newName; // 只在提供方修改状态
});
js
// 子/孙组件 (注入数据)
import { inject } from 'vue';

// 注入值,可以设置默认值
const message = inject('staticMessage', '默认消息');

// 注入响应式数据
const counter = inject('counter');

// 注入方法
const increment = inject('incrementCount');

// 使用Symbol注入键获取数据
const userSymbol = Symbol('user');
const user = inject(userSymbol);
const updateUser = inject('updateUser');

// 使用
const handleClick = () => {
	increment(); // 调用注入的方法修改数据
	console.log(counter.value); // 访问响应式数据

	// 尝试修改user对象(会失败,因为是只读的)
	// user.name = '李四'; // 这会产生警告,因为user是只读的

	// 正确的修改方式是调用提供的方法
	updateUser('李四');
	console.log(user.name); // 输出: 李四
};

// 使用对象形式的inject,可以设置默认值和是否必须
const userConfig = inject('config', { theme: 'light' }, true); // 第三个参数true表示这是必须的

defineExpose

用于子组件向外暴露自身变量、方法提供外部使用

js
// 子组件
import { ref } from 'vue';
const a = ref('');
const test = () => {
	console.log('test');
};

defineExpose({
	a,
	test,
	set: () => {
		a.value = 'bab';
	},
});
vue
<!-- 父组件  -->
<template>
	<A ref="aRef" />
</template>
<script setup>
import { ref, nextTick } from 'vue';
const aRef = ref(''); // 获取dom
nextTick(() => {
	aRef.value.a = 'from-b';
	aRef.value.set();
});
</script>

defineEmits

在父组件中,可以通过监听子组件的 handle-click 事件来获取点击动作

js
// 子组件传递
const emit = defineEmits(['handle-click']);
const handleClick = () => {
	emit('handle-click'); // 触发事件
};
vue
// 父组件接收
<A @handleClick="onSubmit" />

defineOptions

  1. 组件设置组件选项
  2. 相当于以前 export default 中的选项

WARNING

注意: Vue 3.3+新增语法糖

js
/**
  inheritAttrs: 告诉 Vue 不要将未被组件显式接收(props)的属性,自动添加到组件的根元素上.可以自动选择在哪个标签上接收组件传递过来的prop
  比如:
  <!-- 未设置时 -->
  <!-- 使用组件时 -->
  <CommonDrawer class="custom-class" data-test="123" />
  <!-- 组件CommonDrawer内部接收 -->
  <template>
    <div class="drawer-wrapper custom-class" data-test="123">
        <!-- 打算将外部组件的props直接v-bind绑定到这个组件的,但是未设置inheritAttrs:false就会被添加到根标签上 -->
       <el-drawer></el-drawer>
    </div>
  </template>

  <!-- 设置时 -->
  <!-- 使用组件时 -->
  <CommonDrawer class="custom-class" data-test="123" />
  <!-- 组件CommonDrawer内部接收 -->
  <template>
    <div class="drawer-wrapper">
        <!-- 直接将组件的props绑定到所需要的元素上,并且不会自动加到根元素 -->
       <el-drawer v-bind="$attrs"></el-drawer>
    </div>
  </template>
*/
defineOptions({
	inheritAttrs: false,
	name: 'ErMessage',
});
// 等价于
export default {
	name: 'ErMessage',
};

defineProps

js
const props = defineProps({
	code: { type: String, required: true },
	language: { type: String, default: 'javascript' },
});
// 或者
// 需要进行响应式配置,否则获取出现undefined
const props = defineProps(['option']);
const { option } = toRefs(props);
console.log(option);

computed

javascript
const count = ref(1);
const plusOne = computed(() => count.value + 1);

console.log(plusOne.value); // 2

plusOne.value++; // 错误

获取dom

vue
<template>
	<DropdownMenu ref="dropdownRef" />
</template>
<script setup>
const dropdownRef = ref(null); // ref元素
dropdownRef.value.$el;
</script>

获取环境变量

javascript
import.meta.env.VITE_APP_ENV;

全局实例

javascript
const {proxy}: any = getCurrentInstance();

Will Try My Best.