Skip to content

项目

https://www.yuque.com/u158868/ng9lzm/dpnfzvl31qep5yty?singleDoc# 《项目PC+移动》 密码:an1k

vw适配

Vant 2 - Mobile UI Components built on Vue

javascript
yarn add postcss-px-to-viewport@1.1.1 -D
pnpm i postcss-px-to-viewport@1.1.1 -D
  • vite => postcss.config.cjs ; 注意, 因为我们是vite搭建的项目,配置文件.js会报错
javascript
module.exports = {
    plugins: {
        'postcss-px-to-viewport': {
            viewportWidth: 375
        }
    }
}

一级路由配置

javascript
import Vue from 'vue'
import VueRouter from 'vue-router'

// Vite项目,.vue
import Login from '@/views/login.vue'
import Register from '@/views/register.vue'
import Detail from '@/views/detail.vue'
import Layout from '@/views/layout.vue'
Vue.use(VueRouter)

const router = new VueRouter({
    routes: [
        { path: '/login', component: Login },
        { path: '/register', component: Register },
        { path: '/detail/:id', component: Detail },
        {
            path: '/',
            component: Layout
        }
    ]
})

export default router
vue
<template>
    <div id="app">
        <!-- 一级路由出口 -->
        <router-view />
    </div>
</template>

<script>
export default {
    async created() {}
}
</script>

底部导航tabbar

javascript
<template>
    <div class="layout-page">
        <router-view></router-view>

        <!--  van-tabbar路由模式 设置 route属性 -->
        <van-tabbar route>
            <van-tabbar-item icon="home-o">标签</van-tabbar-item>
            <van-tabbar-item icon="search">标签</van-tabbar-item>
            <van-tabbar-item icon="friends-o">标签</van-tabbar-item>
            <van-tabbar-item icon="setting-o">标签</van-tabbar-item>
        </van-tabbar>
    </div>
</template>

<script>
export default {
    name: 'LayoutPage'
}
</script>

<style lang="less" scoped></style>

二级路由

javascript
import Vue from 'vue'
import VueRouter from 'vue-router'

// Vite项目,.vue
import Login from '@/views/login.vue'
import Register from '@/views/register.vue'
import Detail from '@/views/detail.vue'
import Layout from '@/views/layout.vue'
// 二级路由
import Like from '@/views/second/like.vue'
import Article from '@/views/second/article.vue'
import Collect from '@/views/second/collect.vue'
import User from '@/views/second/user.vue'
Vue.use(VueRouter)

const router = new VueRouter({
    routes: [
        { path: '/login', component: Login },
        { path: '/register', component: Register },
        { path: '/detail/:id', component: Detail },
        {
            path: '/',
            component: Layout,
            // 重定向
            redirect: '/article',
            // 二级路由配置
            children: [
                { path: '/article', component: Article },
                { path: '/like', component: Like },
                { path: '/collect', component: Collect },
                { path: '/user', component: User }
            ]
        }
    ]
})

export default router
vue
<template>
    <div class="layout-page">
        <router-view></router-view>

        <!--  van-tabbar路由模式 设置 route属性 -->
        <van-tabbar route>
            <van-tabbar-item to="/article" icon="home-o">面经</van-tabbar-item>
            <van-tabbar-item to="/collect" icon="search">收藏</van-tabbar-item>
            <van-tabbar-item to="/like" icon="friends-o">喜欢</van-tabbar-item>
            <van-tabbar-item to="/user" icon="setting-o">我的</van-tabbar-item>
        </van-tabbar>
    </div>
</template>

<script>
export default {
    name: 'LayoutPage'
}
</script>

<style lang="less" scoped></style>

样式穿透

javascript
<style lang="less" scoped>
// 样式穿透
// 样式设置不上?想去修改子组件样式的时候
// /deep/   >>> stylus
// ::v-deep
::v-deep .van-tabbar-item--active {
    color: orange;
}
</style>

登录页样式

vue
<template>
    <div class="login-page">
        <van-nav-bar title="面经H5登录" />

        <van-form @submit="onSubmit">
            <van-field
                v-model="username"
                name="用户名"
                label="用户名"
                placeholder="用户名"
                :rules="[{ required: true, message: '请填写用户名' }]"
            />
            <van-field
                v-model="password"
                type="password"
                name="密码"
                label="密码"
                placeholder="密码"
                :rules="[{ required: true, message: '请填写密码' }]"
            />
            <div style="margin: 16px">
                <van-button square block type="info" native-type="submit"
                    >提交</van-button
                >
            </div>
        </van-form>
    </div>
</template>

<script>
export default {
    name: 'LoginPage',
    data() {
        return {
            username: '',
            password: ''
        }
    },
    methods: {
        onSubmit(values) {
            console.log('submit', values)
        }
    }
}
</script>

<style lang="less" scoped>
.link {
    color: #069;
    font-size: 12px;
    padding-right: 20px;
    float: right;
}
</style>

请求request模块封装

接口文档:https://apifox.com/apidoc/project-934563/api-20384513 axios文档:https://www.axios-http.cn/docs/instance

新建一个utils/request.js

javascript
import axios from 'axios'
const instance = axios.create({
    baseURL: 'http://interview-api-t.itheima.net',  // 基地址
    timeout: 5000 // 请求超时
})

export default instance

注册页调用试一试

javascript
import request from '@/utils/request.js'
export default {
    name: 'RegisterPage',
    data() {
        return {
            username: '',
            password: ''
        }
    },
    methods: {
        // 点击提交按钮,从表单上获取数据,发送请求
        async onSubmit(values) {
            console.log('submit', values)
            const res = await request.post('/user/register', values)
            console.log(res)
        }
    }
}

toast提示

javascript
async onSubmit(values) {
    try {
        console.log('submit', values)
        const res = await request.post('/h5/user/register', values)
        // 1. 提示注册成功
        this.$toast.success({
            message: '注册成功',
            duration: 1000
        })
        // 2. 跳到登录页
        this.$router.push('/login')
    } catch (err) {
        // 3. 注册失败,提示
        this.$toast.fail(err.response.data.message)
    }
}

响应拦截

javascript
import axios from 'axios'
import { Toast } from 'vant'
const instance = axios.create({
    baseURL: 'http://interview-api-t.itheima.net',
    timeout: 5000
})
// 添加请求拦截器
instance.interceptors.request.use(
    function (config) {
        // 在发送请求之前做些什么
        return config
    },
    function (error) {
        // 对请求错误做些什么
        return Promise.reject(error)
    }
)

// 添加响应拦截器
instance.interceptors.response.use(
    function (response) {
        // 2xx 范围内的状态码都会触发该函数。
        // 对响应数据做点什么
        return response
    },
    function (error) {
        console.log(error)
        if (error.response) {
            // this.$toast()  js文件中不能使用这个this.$toast this不是指向的vm
            Toast(error.response.data.message)
        }
        // 超出 2xx 范围的状态码都会触发该函数。
        // 对响应错误做点什么
        return Promise.reject(error)
    }
)
export default instance

封装登录api/user.js

javascript
import request from '@/utils/request.js'
// 登录
export const login = (params) => {
    // 发送登录的请求
    return request.post('/h5/user/login', params)
}

// 注册
export const regist = () => {}
vue
import { login } from '@/api/user.js'
export default {
    name: 'LoginPage',
    data() {
        return {
            username: '',
            password: ''
        }
    },
    methods: {
        async onSubmit(values) {
            try {
                // 1. 发送请求
                const res = await login(values)
                console.log(res)
                // console.log('submit', values)
                // 2. 如果请求成功,提示
                this.$toast('登录成功')
                // 3. 跳转到首页  /
                this.$router.push('/')
            } catch (err) {
                console.log(err)
            }
        }
    }
}
</script>

极客园PC项目

el-form表单验证

自定义验证

发送短信验证 ==》 login.vue

http://geek.itheima.net/ --> 演示地址上自己发送一条信息来测试登录

javascript
13811111111