路由传参复习
javascript
一、动态路由传参(优雅):
1. 配动态路由(路径中携带参数)
routes: [
{ path: '/detail/:id', component: 组件名 }
]
2. 跳转
<router-link to="/detail/123">去某页面</router-link>
this.$router.push('/detail/123')
this.$router.push({
path: '/detail/123'
})
3. 获取参数
this.$route.params.id
二、query传参(查询参数传参):
1. 路由正常配
routes: [
{ path: '/detail', component: 组件名 }
]
2. 跳转携带参数
<router-link to="/detail?id=123"></router-link>
this.$router.push('/detail?id=123')
this.$router.push({
path: '/detail',
query: {
id: 123
},
// 这里的params会被忽略
})
3. 获取参数
this.$route.query.id
三、params传参,基于内存的参数传递 (刷新会丢失,不太常用)
1. 路由正常配, 额外起个 name
routes: [
{ path: '/detail', name: 'detail', component: 组件名 }
]
2. 跳转, 通过 name 跳转
this.$router.push({
name: 'detail',
query: {},
params: {}
})
3. 获取参数
this.$route.params
Vite
bash
# pnpm i vite@latest -g
# npm i vite@latest -g
桌面上创建一个vite项目
javascript
// pnpm create vite
// cd 项目
// code . 打开vscode
// pnpm i ==> 安装依赖
// 启动项目==> pnpm dev / yarn dev / npm run dev
// pnpm dev --host ==> 可以看到局域网ip
搭配vue2使用
bash
pnpm i @vitejs/plugin-vue2 -D
新建一个vite.config.js
javascript
import vue from '@vitejs/plugin-vue2'
export default {
plugins: [vue()]
}
安装Vue2.7.14
javascript
pnpm i vue@2.7.14
新建src文件,把main.js移入进去
javascript
import Vue from 'vue'
import App from './App.vue'
Vue.config.productionTip = false
new Vue({
render: h => h(App),
}).$mount('#app')
// 修改index.html中main.js的路径
src中新建一个App.vue文件,写一些代码,启动
安装less
bash
pnpm i less less-loader -D
安装vue-router
bash
pnpm i vue-router@3.6.5
配置alias别名
javascript
// vite.config.js
import vue from '@vitejs/plugin-vue2'
import { resolve } from 'path'
export default {
plugins: [vue()],
resolve: {
alias: {
"@": resolve(__dirname, "./src"),
},
}
}
Vue2缺陷
针对对象
javascript
<template>
<div id="app">
<h2>我是通过vite搭建的vue2项目</h2>
<h3>{{ obj.a }}</h3>
<h3>{{ obj.b }}</h3>
<h3>{{ obj.c }}</h3>
<h3>{{ obj.d }}</h3>
<button @click="changeObj">click me</button>
</div>
</template>
<script>
export default {
data() {
return {
obj: {
a: 1
}
}
},
methods: {
changeObj() {
// 3. 如果添加多个响应式属性 , Object.assign({}, this.obj, 新属性)
this.obj = Object.assign({}, this.obj, { c: 777, d: 888 })
}
},
// 最早,可以在这个生命周期中操作数据
created() {
// vue2 针对对象
// 1. Vue无法检测property的添加或者删除(对象上新增的属性不是响应式的,监听不了变化)
// this.obj.b = 2
// 2. 解决方案 this.$set(哪个对象,哪个属性,属性值)
this.$set(this.obj, 'b', 666)
}
}
</script>
<style lang="less"></style>
针对数组
vue
<template>
<div id="app">
<h2>我是通过vite搭建的vue2项目</h2>
<div v-for="item in arr" :key="item">{{ item }}</div>
<button @click="changeArr">click me</button>
</div>
</template>
<script>
export default {
data() {
return {
arr: [1, 2, 3]
}
},
methods: {
changeArr() {
// 1. 利用数组下标 设置值的时候
// this.arr[1] = 666
this.$set(this.arr, 1, 777)
// 2. 修改arr.length 数组长度的时候
// this.arr.length = 2
this.arr.push(9999)
}
},
created() {
// vue2 针对数组
// 解决 =>
// 1. 组件内:vm.$set(vm.arr, 下标,newVal)
// 2. 数组的7个方法,是响应式, 通过这7个方法修改数组,是响应式
// (vue底层,针对数组,改写了数组的原型 Array.prototype => 重写了这7个方法)
// push / pop / shift / unshift / splice / sort / reverse
// Vue2的缺陷
// 1. 针对对象 , 属性的新增和删除,不是响应式
// 2. 针对数组 , ==> Vue底层重写了数组的原型 7个方法
// 2.1 通过数组下标修改值,不是响应式
// 2.3 修改数组的length,不是响应式
}
}
</script>
<style lang="less"></style>
面经基础版
安装less vue-router
bash
pnpm i less less-loader -D
pnpm i vue-router@3.6.5
# layout.vue article-detail.vue 一级路由
配置一级二级路由
javascript
import Vue from 'vue'
import VueRouter from 'vue-router'
// vite里面,不能省略.vue
import Layout from '@/views/layout.vue'
import ArticleDetail from '@/views/article-detail.vue'
// 导入二级路由的四个组件
import Article from '@/views/article.vue'
import Collect from '@/views/collect.vue'
import Like from '@/views/like.vue'
import User from '@/views/user.vue'
Vue.use(VueRouter)
const router = new VueRouter({
routes: [
// 1. 路由规则
{
path: '/',
component: Layout,
// 2. 二级路由,利用children属性配置
children: [
{ path: '/article', component: Article },
{ path: '/collect', component: Collect },
{ path: '/like', component: Like },
{ path: '/user', component: User }
]
},
{ path: '/detail', component: ArticleDetail }
]
})
export default router
指定二级路由出口
vue
<template>
<div class="h5-wrapper">
<div class="content">
<!-- 指定二级路由出口 -->
<router-view></router-view>
</div>
<nav class="tabbar">
<a href="#/article">面经</a>
<a href="#/collect">收藏</a>
<a href="#/like">喜欢</a>
<a href="#/user">我的</a>
</nav>
</div>
</template>
<script>
export default {
name: 'LayoutPage'
}
</script>
路由重定向-高亮
javascript
// 1. 路由规则 重定向
{ path: '/', redirect: '/article' },
// layout.vue 导航高亮
<div class="h5-wrapper">
<div class="content">
<!-- 指定二级路由出口 -->
<router-view></router-view>
</div>
<nav class="tabbar">
<router-link to="/article">面经</router-link>
<router-link to="/collect">收藏</router-link>
<router-link to="/like">喜欢</router-link>
<router-link to="/user">我的</router-link>
</nav>
</div>
安装axios,挂载到Vue原型上
javascript
import axios from 'axios'
// 将axios挂载到Vue原型上,所有组件实例都能访问
Vue.prototype.$axios = axios
// this.$axios.get ==> axios.get
文章列表渲染
vue
<template>
<div class="article-page">
<div class="article-item" v-for="item in articles" :key="item.id">
<div class="head">
<img :src="item.creatorAvatar" alt="" />
<div class="con">
<p class="title">{{ item.stem }}</p>
<p class="other">
{{ item.creatorName }} | {{ item.createAt }}
</p>
</div>
</div>
<div class="body">
{{ item.content }}
</div>
<div class="foot">
点赞 {{ item.likeCount }} | 浏览 {{ item.views }}
</div>
</div>
</div>
</template>
<script>
export default {
name: 'ArticlePage',
data() {
return {
articles: []
}
},
async created() {
const api = 'https://mock.boxuegu.com/mock/3083/articles'
// this.$axios.get(api).then((res) => {
// console.log(res)
// this.articles = res.data.result.rows
// })
const { data } = await this.$axios.get(api)
this.articles = data.result.rows
}
}
</script>
查询参数-动态路由-跳转详情页
javascript
// 路由传参
// 1. 查询参数 ? ?key=val&key2=val2 => this.$route.query.key
// 2. 动态路由 => 改造路由 /路径/:key => this.$route.params.key
// 返回上一页 $router.back() / $router.go(-1)
// article.vue 跳转
@click="$router.push(`/detail/${item.id}`)"
// article-detail.vue
// 取参数
this.$route.params.id
文章详情渲染
javascript
// https://mock.boxuegu.com/mock/3083/articles/:id
vue
<template>
<div class="article-detail-page">
<nav class="nav">
<span class="back" @click="$router.back()"><</span> 面经详情
</nav>
<header class="header">
<h1>{{ article.stem }}</h1>
<p>
{{ article.createdAt }} | {{ article.views }} 浏览量 |
{{ article.likeCount }} 点赞数
</p>
<p>
<img :src="article.creatorAvatar" alt="" />
<span>{{ article.creatorName }}</span>
</p>
</header>
<main class="body">
{{ article.content }}
</main>
</div>
</template>
<script>
export default {
name: 'ArticleDetailPage',
data() {
return {
article: {}
}
},
// 跳转是 $router 取参数是 $route.query/params
async created() {
// 1. 查询参数传的时候,这么取
// console.log(this.$route.query.id)
// 2. 动态路由 ==> 优雅一下
console.log(this.$route.params.id)
const api = `https://mock.boxuegu.com/mock/3083/articles/${this.$route.params.id}`
const { data } = await this.$axios.get(api)
this.article = data.result
}
}
</script>
keep-alive组件缓存
html
<!-- 逗号分隔字符串 -->
<keep-alive include="a,b">
<component :is="view"></component>
</keep-alive>
<!-- 正则表达式 (使用 `v-bind`) -->
<keep-alive :include="/a|b/">
<component :is="view"></component>
</keep-alive>
<!-- 数组 (使用 `v-bind`) -->
<keep-alive :include="['a', 'b']">
<component :is="view"></component>
</keep-alive>
vue
<template>
<div class="h5-wrapper">
<div class="content">
<!-- 指定二级路由出口 -->
<!--
keep-alive 缓存组件 有三个属性
1. include => 缓存哪些组件 ==> 用的多
2. exclude => 不缓存哪些组件
3. max : 最多缓存几个组件
比如 max = 3 , 最多缓存三个组件,当我们缓存了三个,再点切换,又添加了一个缓存,
之前,最近最少使用的哪个组件,不会被缓存 LRU算法
两个生命周期钩子函数
actived(){}
deactived(){}
-->
<keep-alive :include="keepArr">
<router-view></router-view>
</keep-alive>
</div>
<nav class="tabbar">
<router-link to="/article">面经</router-link>
<router-link to="/collect">收藏</router-link>
<router-link to="/like">喜欢</router-link>
<router-link to="/user">我的</router-link>
</nav>
</div>
</template>
<script>
export default {
name: 'LayoutPage',
data() {
return {
keepArr: ['ArticlePage', 'CollectPage']
}
}
}
</script>
面经H5
Vite项目添加eslint校验
GitHub - BingKui/javascript-zh: Airbnb 出品,目前非常流行的 JavaScript 代码规范(中文版)。其内对各种 js 范式的写法进行了详细的规定与说明,按照此规范写出的代码将会更加合理。检测并修复 JavaScript 代码中的问题。 - ESLint - 插件化的 JavaScript 代码检查工具
javascript
// vite项目配置eslint校验
npm init @eslint/config
pnpm create @eslint/config
.eslintrc.cjs
javascript
"rules": {
'no-multiple-empty-lines': "error",
semi: ["error", "never"],
"space-infix-ops": "error"
}
// 1. 不能多个换行
// 2. 是否添加分号
// 3. 运算符左右两边是否有空格
javascript
Ctrl+ shift + P => 打开用户设置, 添加配置
ESlint 插件需要安装
// 当保存的时候,eslint自动帮我们修复错误
"editor.codeActionsOnSave": {
"source.fixAll": true
},
// 保存代码,不自动格式化
"editor.formatOnSave": false
"eslint.enable":false ==> eslint 注释掉
自动格式化
- Prettier - 代码格式化工具
javascript
{
"semi": false,
"singleQuote": true,
"trailingComma": "none",
"tabWidth": 4
}
vscode-settings.json
javascript
"[vue]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
// "[html]": {
// "editor.defaultFormatter": "esbenp.prettier-vscode"
// },
"[javascript]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[typescript]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"editor.defaultFormatter": "esbenp.prettier-vscode", // 默认的代码格式化工具
项目初始化
面经 H5 端 - Vant(上) | zxd’s Blog
index.html
html
<meta
name="viewport"
content="width=device-width,initial-scale=1.0, user-scalable=0"
/>
router/index.js
javascript
import Vue from 'vue'
import VueRouter from 'vue-router'
Vue.use(VueRouter)
const router = new VueRouter({
routes: []
})
export default router
app.vue
vue
<template>
<div id="app">
<!-- 只留下默认的路由出口 -->
<!-- 组件也可以写成但标签的方式-->
<router-view/>
</div>
</template>
安装vant
Vant 2 - Mobile UI Components built on Vue vant-2 版本 => Vue2
bash
pnpm i vant@latest-v2
全局导入
javascript
import Vant from 'vant';
import 'vant/lib/index.css';
Vue.use(Vant);
vue
<template>
<div id="app">
<!-- 只留下默认的路由出口 -->
<!-- 组件也可以写成但标签的方式-->
<!-- <router-view /> -->
<van-button loading type="primary" loading-type="spinner" />
<van-button plain type="info">朴素按钮</van-button>
<!-- 1. 单个日期选择的日历 -->
<!-- <van-cell title="选择单个日期" :value="date" @click="show = true" /> -->
<!-- this.$emit('confirm') -->
<van-calendar v-model="show" @confirm="onConfirm" />
<!-- 2. 日期范围的日历 -->
<van-cell title="选择日期区间" :value="date" @click="show = true" />
<van-calendar v-model="show" type="range" @confirm="onConfirm" />
<!-- 3. slider -->
<van-slider v-model="value" @change="onChange" />
</div>
</template>
<script>
export default {
data() {
return {
date: '',
show: false,
value: 50
}
},
methods: {
formatDate(date) {
return `${date.getMonth() + 1}/${date.getDate()}`
},
onConfirm(date) {
const [start, end] = date
this.show = false
this.date = `${this.formatDate(start)} - ${this.formatDate(end)}`
console.log(this.date)
},
onChange(value) {
// Toast('当前值:' + value)
this.$toast('当前值' + value)
}
}
}
</script>
dayjs格式化日期
javascript
// 1. 全局导入 main.js
import dayjs from 'dayjs'
Vue.prototype.dayjs = dayjs
// 挂载到原型上,通过this.dayjs().format()使用
// 2. 组件内使用
import dayjs from 'dayjs'
dayjs(start).format('YYYY-MM-DD') 使用
vue
<template>
<div id="app">
<!-- 只留下默认的路由出口 -->
<!-- 组件也可以写成但标签的方式-->
<!-- <router-view /> -->
<van-button loading type="primary" loading-type="spinner" />
<van-button plain type="info">朴素按钮</van-button>
<!-- 1. 单个日期选择的日历 -->
<!-- <van-cell title="选择单个日期" :value="date" @click="show = true" /> -->
<!-- this.$emit('confirm') -->
<van-calendar v-model="show" @confirm="onConfirm" />
<!-- 2. 日期范围的日历 -->
<van-cell title="选择日期区间" :value="date" @click="show = true" />
<van-calendar v-model="show" type="range" @confirm="onConfirm" />
<!-- 3. slider -->
<van-slider v-model="value" @change="onChange" />
</div>
</template>
<script>
// import dayjs from 'dayjs'
export default {
data() {
return {
date: '',
show: false,
value: 50
}
},
methods: {
formatDate(date) {
return `${date.getMonth() + 1}/${date.getDate()}`
// YYYY-MM-DD
},
onConfirm(date) {
const [start, end] = date
this.show = false
// this.date = `${this.formatDate(start)} - ${this.formatDate(end)}`
this.date = `${this.dayjs(start).format('YYYY-MM-DD')}-
${this.dayjs(end).format('YYYY-MM-DD')}`
console.log(this.date)
},
onChange(value) {
// Toast('当前值:' + value)
this.$toast('当前值' + value)
}
}
}
</script>
vant按需导入 推荐
注释掉全局导入
javascript
// 全局导入
// import Vant from 'vant'
// import 'vant/lib/index.css'
// Vue.use(Vant)
vite项目 => 按需导入,需要安装插件
- 如果是vue-cli创建的 -->babel.config.js配置 ==> 看vant2文档有说明
javascript
pnpm i unplugin-vue-components -D
// unplugin-vue-components它可以自动引入组件,并按需引入组件的样式。
Vant 中有个别组件是以函数的形式提供的,包括 Toast,Dialog,Notify 和 ImagePreview 组件。在使用函数组件时,unplugin-vue-components 无法自动引入对应的样式,因此需要手动引入样式。--> vant4
javascript
// main.js
// 比如使用$toast,需要在main.js中引入样式
import 'vant/es/toast/style'
vite.config.js配置
javascript
// vite.config.js
import vue from '@vitejs/plugin-vue2'
import { resolve } from 'path'
import Components from 'unplugin-vue-components/vite'
import { VantResolver } from 'unplugin-vue-components/resolvers'
export default {
plugins: [
vue(),
Components({
resolvers: [VantResolver()]
})
],
resolve: {
alias: {
'@': resolve(__dirname, './src')
}
}
}
手动按需导入
main.js中用一个手动导入一个
javascript
import { Calendar, Button, Search } from 'vant';
app.use(Calendar).use(Button).use(Serach)
// app.use(Button)