1, the preface
Yes, it is also a copy of netease Cloud, so many netease cloud projects also write? It’s all about learning.
Vue3, Vite2 and TypeScript have not been available for new projects. I can’t control my hands and have to write them, in order to read the source code and get familiar with the syntax.
The overall code is more concise, the function is more concise, want to practice can continue to expand, many functions are not done.
The project address
Github.com/haiweilian/…
I don’t know how to design the project UI (and some of the logic). Here is a reference to SSH’s open source project
Github.com/sl1673495/v…
Interface used by Binaryify big bro’s open source project.
Github.com/Binaryify/N…
2. Project preparation
After the content is the development of the process of conveniently recorded notes sorted out, to this step can run to write the project.
extension
-
Initialize a project using Vite.
-
Install VSCode Volar for Vue3.
-
Install Vue3’s Chorme extension Vue Devtools 6.x supports both versions 2 and 3.
Project depend on
"dependencies": {
"@vueuse/core": "5.1.0"."axios": "^ 0.21.1"."dayjs": "^ 1.10.5"."element-plus": 54 "^ 1.0.2 - beta."."lrc-kit": "^ 1.1.1"."vue": "^ 3.1.4." "."vue-lazyload-next": "^ hundreds." "."vue-router": "^ 4.0.10"."vuex": "4.0.2."
}
Copy the code
Unified plug-in registration
Put all the plug-ins in the Modules directory and use Vite’s import.meta.globEager to load the registration.
All files in modules return a install function.
// src/modules/element-plus.ts
import type { App } from "vue";
import "element-plus/lib/theme-chalk/base.css";
export const install = (app: App) = > {
app.config.globalProperties.$ELEMENT = { size: "mini" };
};
Copy the code
Import the unified registry using Glob in main.ts.
// src/main.ts
Object.values(import.meta.globEager("./modules/*.ts")).map(i= >i.install? .(app));Copy the code
Vue3
The script Setup syntax used for the whole thing was not finalized at the time of writing and was only partially incompatible after it was finalized. See Script Setup for details.
All dependencies need to be updated and replaced with new syntax. Update dependencies It is recommended to use npm-check-updates to update the entire project.
For example, the changes involved:
-
DefineEmit = > defineEmits.
-
UseContext () -> useSlots() + useAttrs().
-
defineEmits and defineProps no longer need to be imported.
Vuex4
Vuex4 doesn’t change much, except that basically any changes to TS support, such as Store, Commit, dispatch, are not very good hints.
There is a bit of speculation about store in Vue3 that Vuex’s useStore has full state and modules types, but that has to be dealt with separately.
For commit and dispatch, the type is string.
export interface Dispatch {
(type: string, payload? :any, options? : DispatchOptions):Promise<any>; <P extends Payload>(payloadWithType: P, options? : DispatchOptions): Promise<any>; } export interface Commit { (type: string, payload? : any, options? : CommitOptions): void; <P extends Payload>(payloadWithType: P, options? : CommitOptions): void; }Copy the code
Finally, I am looking forward to vex5, and then I will try to change the version with Pinia.
VueRouter4
The routing part of the change is quite a lot of functionality removed, but most of the removed functionality can be done using custom and V-slot.
For example, using arbitrary tag jumps:
<RouterLink v-slot="{ navigate, isExactActive }" :to="menu.link" custom>
<li class="menu-song__item" :class="{'is-active': isExactActive}" @click="navigate">
<Icon :name="menu.icon" />
<span class="menu-song__value"> {{ menu.name }} </span>
</li>
</RouterLink>
Copy the code
TypeScript
After reading the tutorial on the official website, there is basically no problem in writing business. There are several main points in combining with Vue.
Import type Uses type to specify the import type, which is fine if not added to xx.ts, but in Script Setup because top-level variables are automatically collected, “PropType” is only the type, but is used here as a value. Using type also makes it easy to distinguish logic from type.
import { onMounted, ref, watch } from "vue";
import type { PropType } from "vue";
Copy the code
We can’t avoid using library-defined types in our projects, so we can click on them based on the function being called and look at the declaration relationships to find subtypes that are not specified in the documentation.
import { ElLoading } from "element-plus";
import type { ILoadingInstance } from "element-plus/packages/loading/src/loading.type";
let needLoadingRequestCount = 0;
let loading: ILoadingInstance;
Copy the code
VueUse
This library was used in this project and it definitely makes Vue3 feel good.
For example, the use of useStorage, onClickOutside, useMediaControls greatly convenient development.
3. Code specification
Coding standards
The integration of various specifications is not a hassle, is directly using the antFU tycoon extracted from the common configuration. It is a combination of rules and plugins to form a set of plugins, don’t want to toss can be used quickly. You can encapsulate a common set of configurations in this way.
npm i eslint @typescript-eslint/eslint-plugin @antfu/eslint-config --save-dev
Copy the code
In the.eslintrc file, add the following. Get formatting for ESLint & typescript & vue3 & React.
{
"extends": "@antfu"."rules": {
"no-unused-vars": "off"."@typescript-eslint/no-unused-vars": "off"}}Copy the code
Submit specifications
The commit specification uses husKY, CommitLint, Commitizen, and standard-Version configurations as well. Previously summarized various configurations to facilitate the use of coding specifications, submission specifications.
4. CSS naming
The naming style uses the BEM specification, which uses the mixins function in the elemental-plus source code. For details, see Elemental-plus /theme-chalk.
Using SCSS global import in Vite, you can import file paths. Notice the semicolon (;)
export default defineConfig({
css: {
preprocessorOptions: {
scss: {
additionalData: '@import "src/styles/additional.scss"; '}}}});Copy the code
Let’s briefly talk about the main mixins in element-Plus source code: @mixin B ($block), @mixin E ($Element), @mixin M ($Modifier), @mixin when($state).
@mixin b($block)
Define a build block. The parameter is the name of the block.
@include b(input) {
display: inline-block;
}
Copy the code
.el-input {
display: inline-block;
}
Copy the code
@mixin e($element)
Define the generated elements. The parameter is the name of the element and can be passed in more than one.
@include b(input) {
@include e(inner) {
padding: 0 15px;
}
@include e((suffix, suffix-inner)) {
position: absolute; }}Copy the code
.el-input__inner {
padding: 0 15px;
}
.el-input__suffix..el-input__suffix-inner {
position: absolute;
}
Copy the code
@mixin m($modifier)
Define the build modifier. The parameter is the name of the modifier and can be passed in more than one, ($modifier1, $modifier2…) .
@include b(input) {
@include m(medium) {
height: 30px;
}
@include m((mini, small)) {
height: 20px; }}Copy the code
.el-input--medium {
height: 30px;
}
.el-input--mini..el-input--small {
height: 20px;
}
Copy the code
@mixin when($state)
Define the condition state. The parameter is the name of the state.
@include b(input) {
@include when(disabled) {
cursor: not-allowed; }}Copy the code
.el-input.is-disabled {
cursor: not-allowed;
}
Copy the code
5. SVG ICONS
Working with SVG alone is intended to be used as a component, making it easy to switch between states. Use vite-plugin-SVG-icons to do the processing, the use of the document can be viewed.
After configuring the dependencies and Icon directory, create an Icon component.
<template>
<svg :style="getStyle" class="icon" aria-hidden="true">
<use :xlink:href="symbolId" />
</svg>
</template>
<script setup lang="ts">
import { computed } from "vue";
import type { CSSProperties } from "vue";
const props = defineProps({
prefix: {
type: String,
default: "icon",
},
name: {
type: String,
required: true,
},
size: {
type: [Number, String],
default: 16,
},
});
const symbolId = computed(() => `#${props.prefix}-${props.name}`);
const getStyle = computed((): CSSProperties => {
const { size } = props;
let s = `${size}`;
s = `${s.replace("px", "")}px`;
return {
width: s,
height: s,
};
});
</script>
Copy the code
Import or global registration can be used.
<Icon :name="menu.icon" />
Copy the code
6. Request processing
After going through the interface, I found that the data processing level is not good for rendering (because it is easy to do, most of them are not used). Therefore, all fields are uniformly converted using map() before being used.
Take a simple 🌰 :
// The field is namea
[{ namea: "lian" }].map(user= > {
name: user.namea;
});
// The field is nameb
[{ nameb: "lian" }].map(user= > {
name: user.nameb;
});
// After the transformation is consistent, some deep level also directly drawn level.
[{ name: "lian" }];
Copy the code
All interfaces are written to REST Client configuration files.
@hostname = http://localhost:3000
# Query popular comments of corresponding resourcesGET {{hostname}}/comment/hot? id=186016&typeHTTP / 1.1 = 0# query the comment of the corresponding resourceGET {{hostname}}/comment/new? id=186016&typeHTTP / 1.1 = 0 & sortType = 3Copy the code
7. Analysis of lyrics
Lrc-kit will return the parsed array. After parsing, we can loop directly. What we need to do is to locate the lyrics and automatically scroll to the center.
Using LRC-kit, you can get the number of lines at the current time by using curIndex(), get the offset of the element where the lyrics are, and calculate the scrolling distance from the Ref array in V-for.
/** * get the lyric list ref and position the lyric in the middle of the content when the current row change is detected */
const scroller = ref()
const lyricLineRefs = ref<HTMLElement[]>([])
const setItemRef = (el: HTMLElement): void= > {
lyricLineRefs.value.push(el)
}
watch(lineActive, (num: number) = > {
const curDom = lyricLineRefs.value[num]
scroller.value.scrollTop = curDom.offsetTop - 130 + curDom.offsetHeight / 2
})
Copy the code
8. Project deployment
Both projects are deployed on Vercel.
-
Front-end project Deployment
-
Back-end project deployment
9. Conclusion
Thanks for reading, like ✨✨
After this practice, there should be no problem in writing business. Some advanced types of Ts are used sparingly. Then spare time to study Ts advanced types and Vue3 source code.