@author:郭瑞峰 > Vue版本3.2.31 ------ Vue3 组件内的`script`标签设置`setup`属性后,就可以将**相关功能写在一起**,方便维护 但目前**`vscode`**跟**`webstorm`**暂时全面不支持识别这样的语法,故书写时记得配置 eslint注释 例如 ```js // eslint-disable-next-line import Ttt from './Ttt.vue' ``` # 引入组件 组件可以直接引入后调用,无需注册使用 ```vue ``` 但考虑到vue3的`setup`特性无法被其他IDE支持 故要写入注释,防止其他IDE的`eslint`插件**标红** # Data ## data属性 * 常规书写方式 ```js // 写法一 export default { data: () => ({ a: 10, b: 20 }) } ``` ```js // 写法二 export default { data () { return { a: 10, b: 20 } } } ``` ```js // 写法三 vue3 import { defineComponent } from 'vue' export default defineComponent({ data: () => ({ a: 10, b: 20 }) }) ``` * setup + js ```vue {{aaa}} {{JSON.stringify(bbb)}} ``` * setup + ts ```vue {{JSON.stringify(aaa)}} {{bbb}} ``` ### 数据修改 注意:ref注册后**修改数据**,要使用`value`;而reactive不需要 ```js const a = ref(0) a.value++ const b = ref([1, 3, 5]) b.value.push(12) const c = reactive({ name: '张三', age: 13 }) b.age = 33 ``` ## props属性 * 常规书写方式 ```js export default { props: { aaa: { type: [String, Number], default: () => '' } } } ``` * setup + js / setup + ts ```js import { defineProps } from 'vue' // 3.2版本后可以不用引入 const props = defineProps({ aaa: { type: [String, Number], default: () => '' } }) ``` ## computed属性 * 常规书写方式 ```js export default { computed: { aaa () { return 123 } } } ``` * setup + js ```js import { computed } from 'vue' const aaa = computed(() => 123) ``` * setup + ts ```typescript import { computed } from 'vue' const aaa: number = computed((): number => 123) ``` ## methods属性 * 常规书写方式 ```js export default { data: () => ({ a: 1, b: { name: 'joe', age: 10 } }), methods: { aaa () { this.a++ this.b.age++ } } } ``` * setup + js ```js import { ref, reactive } from 'vue' const test1 = ref(123) const test2 = reactive({ name: 'Joe', age: 12 }) const test3 = ref([1, 2, 4]) const testFun = (): void => { // 注意:修改数据时要使用value test1.value++ test2.age++ test3.value.push(7) } ``` * setup + ts ```typescript const test1 = ref(123) const test2 = reactive({ name: 'Joe', age: 12 }) const test3 = ref>([1, 2, 4]) const testFun = (): void => { test1.value++ test2.age++ test3.value.push(7) } ``` ## watch属性 * 常规书写方式 ```js export default { data: () => ({ a: 10, b: { name: 'Joe', age: 11 } }), watch: { a (val) { console.log(val) }, b: { deep: true, immediately: true, handler (val, oldVal) { console.log(val) console.log(oldVal) } } } } ``` * setup + js ```javascript import { reactive } from 'vue' const obj = reactive({ name: '张三', age: 12 }) const aaafun = () => { aaa.value += 1 obj.value.age += 1 } watch(obj, (val) => { console.log(val) }, { deep: true, immediate: true }) /* * watch(被监听的数据, 监听操作(函数/方法), 配置(如深度监听、立即执行)) * 注意:若是对象类被监听,val和oldVal数据一致,都是变化后的数据 * */ // 监听对象数据变化(只是第一层) watch(() => ({ ...obj }), (val, oldVal) => { console.log(val) console.log(oldVal) }, { deep: true, immediate: false }) ``` * setup + ts ```typescript const obj = reactive({ name: '张三', age: 12 }) const aaafun = (): void => { aaa.value += 1 obj.value.age += 1 } watch(obj, (val: unknown, oldVal: unknown) => { console.log(val) console.log(oldVal) }, { deep: true, immediate: true }) /* * watch(被监听的数据, 监听操作(函数/方法), 配置(如深度监听、立即执行)) * 注意:若是对象类被监听,val和oldVal数据一致,都是变化后的数据 * */ // 监听对象数据变化(只是第一层) watch(() => ({ ...obj }), (val: unknown, oldVal: unknown) => { console.log(val) console.log(oldVal) }, { deep: true, immediate: false }) ``` ## Vue3 不支持 filter过滤器 ## emit属性 作用:向上传递信息时进行校验 * 常规书写方式 ```ts import { defineComponent } from 'vue' export default defineComponent({ emit: { /* data为向上传递的数据 */ emitCount: (data: number):boolean => { if (data < 1) { return false } return true } } }) ``` * setup + ts ```ts import { defineEmit } from 'vue' // 3.2版本后可以不用引入 const emit = defineEmit({ emitCount: (data: number): boolean => { if (data < 1) { return false } return true } }) ``` ## expose属性 作用:导出子组件内部分属性/方法 * 常规书写方式 ```js // 子组件 import { defineComponent, ref } from "vue" export default defineComponent({ data: function () { return { count: ref(0) } }, methods: { setCount (num: number = 1) { this.count += num } }, expose: ['count', 'setCount'] // 注册被导出属性、方法 }) ``` ```js // 父组件 import { defineComponent, ref } from 'vue' import ChildrenComponent from './ChildrenComponent.vue' export default defineComponent({ components: { ChildrenComponent }, data () { return { childrenDom: ref() } }, mounted () { this.childrenDom = this.$refs.children // 获取子组件dom console.log(this.childrenDom.count) // 调用子组件的属性 }, methods: { setChildrenNum () { this.childrenDom.setCount(10) // 调用子组件的方法 } } }) ``` * setup + ts ```ts // 子组件 import { ref, defineExpose } from 'vue' defineProps<{ msg: string }>() const count = ref(0) const fff = ref(12) const setCount = (data: number, hasReturn: boolean = false): void | number => { count.value = data if (hasReturn) { return data } return } defineExpose({ count, fff, setCount }) ``` ```ts // 父组件 import { onMounted, ref } from 'vue' import Kid from './components/Kid.vue' // 绑定子组件dom const kid = ref(null) const fun = () => { kid.value.setCount(kid.value.count + 10) } onMounted(() => { console.log(kid.value.fff) console.log(kid.value.count) }) ``` # 组件通信 ## 父子组件通信 * 常规书写方式 ```js export default { data: () => ({ obj: { name: 'Joe', age: 13 } }), methods: { test () { this.$emit('aaa', obj) } } } ``` * setup + js ```js import { defineEmits } from 'vue' // 第一步:注册emits通信名称 const emits = defineEmits(['test1', 'test2', 'test3']) // 第二部:使用通信传输 const submit = () => { // 传输名 + 传输数据 emits('test1', { name: '张三', age: 12 }) } ``` * setup + ts ```typescript import { defineEmits } from 'vue' // 第一步:注册emits通信名称 const emits = defineEmits(['test1', 'test2', 'test3']) // 第二部:使用通信传输 const submit = (): void => { // 传输名 + 传输数据 emits('test1', { name: '张三', age: 12 }) } ``` ## Vuex通信 * 常规书写方式 ```js // ...... console.log(this.$store.state.list) this.$sotre.commit('setList', [1, 2, 3, 4, 5]) this.$store.dispatch('pushList', 200) // ...... ``` * setup + js / setup + ts ```js import { useStore } from 'vuex' const store = useStore() store.commit('setList', [0, 1, 2, 3, 4, 5, 6, 7]) store.dispatch('pushList', 200) console.log(store.state.list) ``` # dom节点操作 ## 获取dom * 常规书写方式 ```vue h1第一个标签 h1第二个标签 ``` * setup + js / setup + ts ```vue h1第一个标签 ```  若是要对dom节点操作,需要使用`value`属性 ## 父组件获取/使用子组件属性/方法 注:这是Vue3.2之后 * 常规书写方式 ```ts // 子组件 import { defineComponent, ref } from "vue" export default defineComponent({ name: 'ChildrenComponent', data: function () { return { count: ref(0) } }, methods: { setCount (num: number = 1) { this.count += num } }, expose: ['count', 'setCount'] }) ``` ```ts // 父组件 import { defineComponent, ref } from 'vue' import ChildrenComponent from './ChildrenComponent.vue' export default defineComponent({ components: { ChildrenComponent }, data () { return { childrenDom: ref() } }, mounted () { this.childrenDom = this.$refs.children // 获取子组件 console.log(this.childrenDom.count) // 调用子组件属性 }, methods: { setChildrenNum () { this.childrenDom.setCount(10) // 调用子组件方法 } } }) ``` * setup + ts ```ts // 子组件 import { ref, defineExpose } from 'vue' defineProps<{ msg: string }>() const count = ref(0) const fff = ref(12) const setCount = (data: number, hasReturn: boolean = false): void | number => { count.value = data if (hasReturn) { return data } return } defineExpose({ count, fff, setCount }) ``` ```ts // 父组件 import { onMounted, ref } from 'vue' import Kid from './components/Kid.vue' import ParentComponent from './components/ParentComponent.vue'; const kid = ref(null) const fun = () => { kid.value.setCount(kid.value.count + 10) } onMounted(() => { console.log(kid.value.fff) console.log(kid.value.count) }) ``` # 生命周期 | 生命周期说明 | Vue2 | Vue3 | Vue3 setup | | ------------------ | ------------- | ------------- | --------------- | | 组件实例化前 | beforeCreate | 同左 | 无 | | 组件实例化后 | created | 同左 | 无 | | 组件dom前 | beforeMount | 同左 | onBeforeMount | | 组件dom后 | mounted | 同左 | onMounted | | 组件更新前 | beforeUpdate | 同左 | onBeforeUpdate | | 组件更新后 | updated | 同左 | onUpdated | | 组件销毁前 | beforeDestroy | beforeUnmount | onBeforeUnmount | | 组件销毁后 | destroyed | unmounted | onUnmounted | | 了解 | | | | | keep-alive组件激活 | activated | 同左 | onActivated | | keep-alive组件失活 | deactivated | 同左 | onDeactivated | | 组件加载错误 | errorCaptured | 同左 | onErrorCaptured | * vue3 setup使用周期函数方法 ```js import { onBeforeMount, onMounted, onBeforeUpdate, onUpdated, onBeforeUnmount, onUnmounted } from 'vue' console.log('setup') onBeforeMount(() => { console.log('beforeMount') }) onMounted(() => { console.log('mounted') }) onBeforeUpdate(() => { console.log('beforeUpdate') }) onUpdated(() => { console.log('updated') }) onBeforeUnmount(() => { console.log('beforeUnmounte') }) onUnmounted(() => { console.log('unmounted') }) ``` **注意**: 1. setup是在生命周期的`beforeCreate`和`created`**之前**执行的 2. 在父子组件中,setup是在父组件的`beforeMount`**之后**执行的 3. Vue3 父子组件生命周期执行顺序与 Vue2 有区别:Vue2父子组件:before先夫后子,after先子后夫;Vue3是父组件`beforeMount`钩子之前(包括`beforeMount`)不会执行子组件,子组件的`setup`、`beforeCreate`、`created`和`beforeMount`会在父组件的`beforeMount`和`mounted`之间执行 # 路由vue-router | 说明 | 常规 | 组合式 | | ------------ | -------------- | ---------------------------- | | 路由操作 | `this.$router` | `const router = useRouter()` | | 当前路由信息 | `this.$route` | `const route = useRoute()` | # 代码折叠技巧 ## WebStorm webstorm支持自动折叠代码 ```js // region 被折叠部分 // endregion ``` 故可以将同一功能模块写在一起,再用折叠代码折叠,便于后期维护以及项目二次开发 例子: ```js // 查询功能 // region 相关数据、方法、校验、接口等等 // endregion ``` | 语言类型 | 折叠代码 | | ---------------- | ----------------------------------- | | JavaScript | `// region`、`// endregion` | | css、css预编译器 | `/* region */`、`/* endregion */` | | html | ``、`` | | TypeScript | `// region`、`// endregion` | ## VSCode VSCode也支持自动折叠代码,但书写部分与WebStorm有区别 | Language | Start region | End region | | :-------------------- | :------------ | :--------------- | | CSS/Less/SCSS | `/*#region*/` | `/*#endregion*/` | | TypeScript/JavaScript | `//#region` | `//#endregion` | ------ @endDate: 2021/10/26 # 更新时间 * 2022/04/15 * 2022/04/12 * 2022/04/11 * 2021/10/26 最后修改:2023 年 04 月 04 日 © 允许规范转载 赞 0 如果觉得我的文章对你有用,请随意赞赏
1 条评论
操作步骤清晰,指导性强,易于实践。