说明
采用vite
和组合式api
的方式构建项目
Vue官网
Vue-Router官网
创建项目
确保你安装了最新版本的 Node.js,并且你的当前工作目录正是打算创建项目的目录。在命令行中运行以下命令:
npm create vue
除了router
和pinia
选择yes
其余全部选择no
在项目被创建后,通过以下步骤安装依赖并启动开发服务器:
cd <your-project-name>
npm install
npm run dev
初始化配置
Network: use --host to expose
解决:
在vite.config.js
文件下的defineConfig
里加入如下配置:
server: {
host:true
},
删除初始信息
只保留router
、stores
、homeview
、app.view
和main.js
里的内容。直到不报错。
# components 全删
# stores 不动
# router index.js
import { createRouter, createWebHistory } from 'vue-router'
import HomeView from '@/views/HomeView.vue'
const router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL),
routes: [
{
path: '/',
name: 'home',
component: HomeView
},
]
})
export default router
# views 只保留HomeView.vue 最基本的格式
# App.vue
<script setup>
</script>
<template>
<RouterView />
</template>
<style scoped>
</style>
# main.js 删掉第一行引入的.css
安装插件
安装Bootstrap
通过npm
下载Bootstrap
Bootstrap下载地址
在App.vue
中引入css
和js
import 'bootstrap/dist/css/bootstrap.css';
import "bootstrap/dist/js/bootstrap";
安装ElementPlus
通过npm
下载ElementPlus
ElementPlus安装地址
在main.js
中引入ElementPlus
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
app.use(ElementPlus)
安装axios
axios官网
通过npm
下载axios
npm install axios
单组件引用axios
import axios from 'axios';
安装jQuery
npm i jquery
Bootstrap常用效果
NavBar
设计导航栏
.container
.container-fluid
会占满整个布局,去掉fluid
会使元素向中间聚集。
Cards
卡片,用框把页面括起来
<div class="card">
<div class="card-body">
This is some text within a card body.
</div>
</div>
Grid
页面布局等分:
<div class="container text-center">
<div class="row">
<div class="col-4">
Column
</div>
<div class="col-4">
Column
</div>
<div class="col-4">
Column
</div>
</div>
</div>
居中
当只划分出一个col
若要使grid居中
只需在 row
后加上 justify-content-md-center
即加入类名
Images
图片自适应大小:class="img-fluid"
“.d-flex ms-auto”类
要将导航栏登录和注册按钮
移动到导航栏的右边
,可以使用Flexbox
布局并给ul
元素添加d-flex
类以及ms-auto
类,来自动填充左侧空间
常见问题
引入组件
组件不需要export
导出,在引入时直接引入即可,主要需要加上后缀.vue。例如:
import NavBar from './components/NavBar.vue'
jwt-decode
安装解构包
npm i jwt-decode
引入
import {jwtDecode} from 'jwt-decode'
slot
例如当系统的每个页面都有相同的布局时(每个页面都被框框框起来了),那么可以创建一个ContentBase.vue
组件,将这些重复的工作提取出来,通过
<slot/>
动态渲染每个页面的内容。每个页面只需要引入组件ContentBase.vue
即可。其组件里的内容会通过<slot/>
出现。
//ContentBase.vue:
<div class="container">
<div class="card">
<div class="card-body">
<slot/>
</div>
</div>
</div>
//HomeView.vue:
<ContentBase>
首页
</ContentBase>
路由Router
添加路由
在router
文件夹下的index.js
文件中按照Homeview
添加其他页面路由。
代表的含义:
path
:代表路径
name
:起的名字
component
: 对应的页面
比如以后访问登录
页面,可以通过http://localhost:5173/login/
访问
未匹配到页面跳转到404
{
path: '/:pathMatch(.*)*',
name: 'NotFound',
component: NotFoundView
},
带参数的路由
在你的组件中使用 $route
或 useRoute()
会与路由紧密耦合
,这限制了组件的灵活性,因为它只能用于特定的 URL。因此我们建议通过 props
配置来解除这种行为:
//router 带参数路径
{
path: '/userprofile/:userId',
name: 'userprofile',
component: UserProfileView,
props: true,
},
//带参数命名路由:
<router-link class="nav-link" :to="{name:'userprofile',params:{userId:2}}">用户动态</router-link>
//props配置
const props = defineProps({
userId: Number,
});
//在页面中使用userId
template中 {{userId}}
script中 console.log(props.userId);
//子组件使用userId需要通过父组件传值
命名路由
我们可以使用 name
而不是 path
来传递 to
属性给 <router-link>
这种方式可以实现切换页面不重新加载。
<router-link :to="{ name: 'profile', params: { username: 'erina' } }">
User profile
</router-link>
router.push跳转
router.push({name:'login'});
父子传值
父组件向子组件传值
数据定义在父组件,通过v-bind
绑定子组件,子组件通过defineProps
接受传入的对象。之后可以在template
直接使用传入的对象,在script
中需要用定义的局部属性,通过props.对象.属性
的方式获取数据。
注意:prop
被用于传入初始值;而子组件想在之后将其作为一个局部数据属性。在这种情况下,最好是新定义一个局部数据属性
,从props
上获取初始值即可:
//父组件数据:
const user = reactive({
id: 1,
username: "caozheng",
lastName: "cao",
firstName: "zheng",
followerCount: 0,
is_followed: false
});
//v-bind绑定子组件:
<UserProfileInfo :user="user"></UserProfileInfo>
//接受对象,并定义局部数据属性
const props = defineProps({
user: {
type: Object,
required: true
}
});
//computed() 动态计算
const fullName = computed(()=>{
return props.user.lastName + props.user.firstName;
})
子组件向父组件传值
数据在哪定义的就要在哪修改
先通过defineEmits(["..",".."])
定义局部变量emit
, 然后通过emit("父组件起的事件名")
向父组件传递事件,之后父组件会调用对应函数,修改数据。
//创建emit defineEmits([]) 其中[]里是数组,存储传递的事件名
const emit = defineEmits(["follow","unfollow"]);
// 子组件通过函数调用,通过emit向父组件传值
const follow = () =>{
console.log("follow");
emit("follow",参数); //可以没有参数
}
//父组件通过@follow接受,在调用"follow"函数,修改数据
<UserProfileInfo :user="user" @unfollow="unfollow" @follow="follow"></UserProfileInfo>
// 注意:emit("follow"),@follow,defineEmits(["follow"]) 这几处的follow(名字)要一致。
//父组件函数,修改数据。传递的参数只在此函数中使用
const follow = (参数) => {
if(user.is_followed) return;
user.is_followed = true;
user.followerCount ++;
}
pinia
定义一个Store
export const 自定义的名 = defineStore('自定义的名的中间部分',() =>{
state: 定义的对象
getter:computed计算属性
action:定义的函数
return{定义的对象,函数}
});
异步操作async
//异步需要加上async关键字
const login = async (data)=>{
内容
}