vue-3
项目创建
创建一个 Vue 应用 npm create vue@latest
根据提示选择自己想要的项目
用 npm 安装
https://cn.vuejs.org/guide/quick-start.html#creating-a-vue-application
选择: TS、 Vue Router、 Pinia、 ESlint 、 Prettier
- 开启 "typescript.validate.enable": true, 用户设置,eslint 即可生效
基础语法
Vue Class Component :使用类的形式写 vue 组件 地址
组件不强制要求唯一跟标签
编写组件引入时 会报 TS6307 重启一下编辑器就好
只需要安装 Sass 包 才能正常使用 sass
app.component('SomeName', SomeComponent)
名称用大驼峰 使用时可以用<SomeName/> <some-name/>
引入一些类型
import type { CSSProperties } from 'vue' // css 属性
周期函数
https://v3.cn.vuejs.org/guide/composition-api-lifecycle-hooks.html
Hooks 和 Mixins
mixins 的缺点: 1. 数据来源不明,因为是隐式传入,没有显示的调用,都是传进来后自动挂载; 2. 同名的数据和方法问题 3. minins 和组件是多对多的关系,会导致定位问题异常复杂
hooks 可以独立抽取为方法,封装 CompositionAPI,然后各地方独立引用
composition API 组合式 API
获取元素
<!-- 这里ref的值和下面返回的值要一致 -->
<div ref="myRef">ref</div>
import { ref, getCurrentInstance } from 'vue';
setup() {
const myRef = ref(null);
// myRef.value // 返回DOM
const { proxy } = getCurrentInstance();
proxy.myRef // 返回DOM
return myRef
}
setup
在 beforCreate 之前执行,并且替换了 beforCreate created 周期函数
返回值:
- 对象(对象的属性、方法,在模板中可以直接使用)
- 函数(定义渲染内容) 参考下方示例
import { defineComponent, ref, h } from "vue";
export default defineComponent({
setup(props) {
/**
* props 使用时不要直接用es6的解构,如果要用,可以用 toRefs 处理后解构 组件外部传递进来 且组件内部声明接收了的属性
* context 上下文对象
* context.attrs 组件外部传入的 没有在 props 配置中声明的属性,相当于 this.$attrs
* context.slots 相当于 this.$slots
* context.emit 相当于 this.$emit
*/
const value = ref(0);
/* 返回一个对象 */
return {
value,
};
/* 返回一个渲染函数, 模板内容会被全部替换为该内容 */
// return () => h('pre', 'code pre')
},
});
setup 语法糖
// 组件直接引入,可以直接使用
import { defineProps } from "vue"; // 定义 props
defineProps({
info: {
type: String,
default: "",
},
});
- reactive() 创建响应数据 类似原来的 data 数据
ref()
目的是让一些定义的基本数据类型,可以成为响应式的数据
基本数据类型,响应式依然使用的是 Object.defineProperty()
返回的是 refImpl (reference implement) 引用实现的实例对象,通俗的叫法是 引用对象
对象类型数据:响应式采用 reactive; ref(obj) 等价于 reactive({value: obj}),原理是采用 Proxy 拦截 然后 使用 Reflect 对属性进行操作
当挂载到 reactive() 上时,会自动把响应式数据对象展开为原始的值,不需通过 .value 就可以直接被访问
vue 模板中使用可以不加 .value 访问, js 代码中通过 .value 获取变量值
用 isRef 来判断是否是 ref() 创建的值
reactive()
定义对象的响应式数据 (无法处理基本类型)
原理是使用 Proxy 代理拦截,所以利用下标修改数组 也可以被监听到
可直接获取对象属性
- toRefs()
将 reactive() 创建出来的响应式对象,转换为每个属性节点都是 ref() 类型的响应式数据
- 返回 state 时 如果要解构对象,需要用 toRefs 处理一下
computed() 函数
用来创建计算属性,返回值是一个 ref 的实例
import { computed, ref } from "vue";
const count = ref(0);
// 只读
const add = computed(() => count.value + 1);
// 可读 可赋值
const addPlus = computed({
get() {
return count.value;
},
set(val) {
count.value = val;
},
});
// 可赋值的使用
addPlus.value = addPlus.value + 4;
provide() 和 inject()
可以实现嵌套组件之间的数据传递。在 setup() 函数中使用。父级组件中使用 provide() 函数向下传递数据;子级组件中使用 inject() 获取上层传递过来的数据。
watchEffect | watch
/**
* 1. 立即执行 2. 可以停止监听 3. 会自动收集依赖 4.只能监听某个值,不能监听对象 5. 不能获取oldvalue newvalue
* 6. 内部可以有异步操作
*/
const stop = watchEffect(() => {
console.log(count.value);
});
const handleAdd = () => {
count.value++;
};
// stop
const handleStop = () => {
stop(); // 监听不再有效
};
/**
* 第一个参数可以为以下
* 第二个参数为回调函数
* 第三个参数可以为:immediate deep
* 参考: https://cn.vuejs.org/api/reactivity-core.html#watch
*/
// 1. 一个函数返回一个值:一般用于监听 reactive 的属性,因为不能直接监听reactive属性,所以采用函数返回值的形式
const re = reactive({ count: 1 }); // 触发:re.count = 2
/* 监听 props 值,如 re.count 替换成 props.someKey */
watch(
() => re.count,
(newVal, oldVal) => {
console.log("watch", newVal, oldVal);
}
);
// 2. 侦听源是一个 ref:
const rf = ref(0); // 触发:rf.value = 1
watch(rf, (newVal, oldVal) => {
console.log("rf watch:", newVal, oldVal);
});
// 3. 直接监听响应式对象,侦听器自动处于深层级模式,注意无法得到旧值
const re = reactive({ count: 1 }); // 触发:re.count = 2
watch(re, (newVal, oldVal) => {
console.log("re watch:", newVal, oldVal);
});
// 4. 当使用函数作源时,只在此函数的返回值发生变化时才会启动。需要明确地用 { deep: true } 才能进入深层级模式
// const re = reactive({ count: 1 }) // 触发:re.count = 2
watch(
() => re,
(newVal, oldVal) => {
console.log("re watch:", newVal, oldVal);
},
{ deep: true }
);
// 5. 一个数组
const re = reactive({ count: 1 });
const rf = ref(0);
watch(
[re, rf],
([ren, rfn], [reo, rfo]) => {
// 第一个数组全是新值,第二个数组全是旧值
console.log("re rf", ren, rfn, reo, rfo);
},
{ deep: true }
);