# 用 vite 初始化项目
初始化项目
代码语言:javascript复制mkdir vuejs && cd vuejs
npm init @vitejs/app
# √ Project name: ... cellinlab-admin
# √ Select a framework: » vue
# √ Select a variant: » vue
cd cellinlab-admin/
npm install
npm run dev
引入 vuex 和 vue-router
代码语言:javascript复制npm install vuex@next vue-router@next
# 约定规范
代码语言:javascript复制|-src
| |- api 数据请求
| |- assets 静态资源
| |- components 组件
| |- pages 页面
| |- router 路由配置
| |- store vuex 数据
| |- utils 工具方法
创建路由
代码语言:javascript复制// src/router/index.js
import { createRouter, createWebHashHistory } from 'vue-router';
import Home from '../pages/home.vue';
import About from '../pages/about.vue';
const routes = [
{
path: '/',
name: 'Home',
component: Home,
},
{
path: '/about',
name: 'About',
component: About,
}
];
const router = createRouter({
history: createWebHashHistory(),
routes,
});
export default router;
创建对应的页面
代码语言:javascript复制<template>
<h2>
Home Page
</h2>
</template>
代码语言:javascript复制
<template>
<h2>
About Page
</h2>
</template>
在 main.js 中引入路由
代码语言:javascript复制// src/main.js
import { createApp } from 'vue'
import App from './App.vue'
import router from './router/index'
createApp(App)
.use(router)
.mount('#app')
在 App.vue 中加入跳转链接
代码语言:javascript复制<template>
<div>
<router-link to="/">Home</router-link>
<router-link to="/about">About</router-link>
</div>
<router-view></router-view>
</template>
项目雏形形成:
在实际项目开发中还会有各种工具的集成:
# Composition API 和 script setup
# Hello World
src/components/TodoList.vue
:
<template>
<div>
<input type="text" v-model="title" @keydown.enter="addTodo" />
<button v-if="active < total" @click="clear">Clear</button>
<ul v-if="todolist.length">
<li v-for="todo in todolist">
<input type="checkbox" v-model="todo.done" />
<span :class="{ done: todo.done }">{{ todo.title }}</span>
</li>
</ul>
<p v-else>No todos yet!</p>
<div>
Select All!
<input type="checkbox" v-model="allDone" />
<span>{{active}} / {{total}}</span>
</div>
</div>
</template>
<script setup>
import { ref, computed } from 'vue';
let title = ref('');
let todolist = ref([]);
function addTodo() {
todolist.value.push({
title: title.value,
done: false
});
title.value = '';
}
function clear () {
todolist.value = todolist.value.filter(todo => !todo.done);
}
let active = computed(() => {
return todolist.value.filter(todo => !todo.done).length;
});
let total = computed(() => {
return todolist.value.length;
});
let allDone = computed({
get: function () {
return active.value === 0;
},
set: function (value) {
todolist.value.forEach(todo => {
todo.done = value;
});
}
});
</script>
<style scoped>
h1 {
color: red;
}
.done {
text-decoration: line-through;
}
</style>
# Composition API 拆分代码
如果在一个页面里有多个功能,那就需要在 data 和 methods 里分别进行配置。但这样的话,数据和方法相关的代码会写在一起,在组件代码行数多了后就不好维护。可以使用 Composition API 的逻辑来拆分代码,把一个功能相关的数据和方法都维护在一起。
代码语言:javascript复制<template>
<div>
<input type="text" v-model="title" @keydown.enter="addTodo" />
<button v-if="active < total" @click="clear">Clear</button>
<ul v-if="todolist.length">
<li v-for="todo in todolist">
<input type="checkbox" v-model="todo.done" />
<span :class="{ done: todo.done }">{{ todo.title }}</span>
</li>
</ul>
<p v-else>No todos yet!</p>
<div>
Select All!
<input type="checkbox" v-model="allDone" />
<span>{{active}} / {{total}}</span>
</div>
</div>
</template>
<script setup>
import { ref, computed } from 'vue';
let {
title,
todolist,
addTodo,
clear,
active,
total,
allDone
} = useTodos();
function useTodos () {
let title = ref('');
let todolist = ref([]);
function addTodo() {
todolist.value.push({
title: title.value,
done: false
});
title.value = '';
}
function clear () {
todolist.value = todolist.value.filter(todo => !todo.done);
}
let active = computed(() => {
return todolist.value.filter(todo => !todo.done).length;
});
let total = computed(() => {
return todolist.value.length;
});
let allDone = computed({
get: function () {
return active.value === 0;
},
set: function (value) {
todolist.value.forEach(todo => {
todo.done = value;
});
}
});
return {
title,
todolist,
addTodo,
clear,
active,
total,
allDone
};
}
</script>
<style scoped>
h1 {
color: red;
}
.done {
text-decoration: line-through;
}
</style>
在使用 Composition API 拆分功能时,也就是执行 useTodos 的时候,ref、computed 等功能都是从 Vue 中单独引入,而不是依赖 this 上下文。其实可以把组件内部的任何一段代码,从组件文件里抽离出一个独立的文件进行维护。
src/utils/mouse.js
:
import { ref, onMounted, onUnmounted } from "vue";
export function useMouse () {
const x = ref(0);
const y = ref(0);
function update (e) {
x.value = e.clientX;
y.value = e.clientY;
}
onMounted(() => {
window.addEventListener("mousemove", update);
});
onUnmounted(() => {
window.removeEventListener("mousemove", update);
});
return { x, y };
};
使用 useMouse.js :
代码语言:javascript复制<template>
<div>x:{{x}},y:{{y}}</div>
</template>
<script setup>
import { useMouse } from '../utils/mouse';
let { x, y } = useMouse();
</script>
因为 ref 和 computed 等功能都可以从 Vue 中全局引入,所以就可以把组件进行任意颗粒度的拆分和组合,这样就大大提高了代码的可维护性和复用性。
# <script setup>
<script setup>
是为了提高使用 Composition API 的效率而存在的,使用 <script setup>
可以让代码变得更加精简,这也是现在开发 Vue 3 项目必备的写法。