Skip to content

路由传参复习

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>

面经基础版

image.png

安装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()">&lt;</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

image.png .eslintrc.cjs

javascript
    "rules": {
        'no-multiple-empty-lines': "error", 
        semi: ["error", "never"],
        "space-infix-ops": "error"
    }

// 1. 不能多个换行
// 2. 是否添加分号
// 3. 运算符左右两边是否有空格

image.png

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
}

image.png 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)