其他分享
首页 > 其他分享> > vue3进阶学习

vue3进阶学习

作者:互联网

vue3进阶学习

官方网站:https://v3.vuejs.org/

中文文档: https://staging-cn.vuejs.org/guide/introduction.html

目的

1、Vue3安装

上节我们采用NPM 的方法来学习vue。

这次使用构建工具来构建Vue项目。

现在官方推荐使用 create-vue 来创建基于 Vite 的新项目

1.1、Vite简单了解

官方中文文档:https://cn.vitejs.dev/

官方推荐使用Vite来构建vue项目,这里简单了解一下。

Vite主要功能是用于打包场景的增强功能。

Vite作为一个基于浏览器原生ESM的构建工具,它省略了开发环境的打包过程,利用浏览器去解析imports,在服务端按需编译返回。同时,在开发环境拥有速度快到惊人的模块热更新,且热更新的速度不会随着模块增多而变慢。因此,使用Vite进行开发,至少会比Webpack快10倍左右。

1.2、项目构建

前提条件

1、通过命令来初始化 vue3 项目。

npm init vue@latest

创建项目时,可以根据自己需求去添加组件。

2、启动项目

# 进入刚刚创建项目的目录
cd vue3-demo
# 更新依赖
npm install
# 启动项目
npm run dev

访问 http://127.0.0.1:5173/

1.3、项目结构说明

1、新建目录如下:

打开APP.vue,你会发现Vue 的单文件组件是网页开发中 HTML、CSS 和 JavaScript 三种语言经典组合的自然延伸。<template><script><style> 三个块在同一个文件中封装、组合了组件的视图、逻辑和样式。完整的语法定义可以查阅 SFC 语法说明

1.4、添加登录页面

1、把对应没有用的页面先删除。

2、编写登录页

App.vue

<script setup>
import Login from './views/Login.vue'
</script>
<template>
  <main>
    <Login />
  </main>
</template>

<style scoped>
</style>

创建views文件夹,我们一般会将页面放在views里。

Login.vue

<script setup>
</script>

<template>
    <div class="container">
        <div class="login-wrapper">
            <div class="header">登录</div>
            <div class="form-wrapper">
                <input type="text" name="username" placeholder="账号" class="input-item">
                <input type="password" name="password" placeholder="密码" class="input-item">
                <div class="btn">登录</div>
            </div>
        </div>
    </div>
</template>

<style scoped>
        .container {
            height: 100%;
        }
        .login-wrapper {
            background-image: linear-gradient(to right, #fbc2eb, #a6c1ee);
            width: 358px;
            height: 588px;
            border-radius: 15px;
            padding: 0 50px;
            margin: 0 auto;
        }
        .header {
            font-size: 38px;
            font-weight: bold;
            text-align: center;
            line-height: 200px;
        }
        .input-item {
            display: block;
            width: 100%;
            margin-bottom: 20px;
            border: 0;
            padding: 10px;
            border-bottom: 1px solid rgb(128, 125, 125);
            font-size: 15px;
            outline: none;
        }
        .input-item:placeholder {
            text-transform: uppercase;
        }
        .btn {
            text-align: center;
            padding: 10px;
            width: 100%;
            margin-top: 40px;
            background-image: linear-gradient(to right, #a6c1ee, #fbc2eb);
            color: #fff;
        }
</style>

效果如果下:

1.5、模拟登录成功跳转页面

Vue Router官方文档:https://router.vuejs.org/zh/

1、添加Vue Router依赖

由于页面跳转需要路由(相当于控制你要去哪个页面的控制器)。

# 在项目的根目录下
npm install vue-router@4

2、添加router文件

可以新增routers文件夹,存放router文件,看个人习惯。

添加router文件

import { createRouter, createWebHistory } from 'vue-router'

// 导入路由组件.
import Login from './views/Login.vue'
import UserList from './views/UserList.vue'

// 创建路由实例
export const router = createRouter({
    history: createWebHistory(),
    // 定义路由
    routes: [
        { path: '/', component: Login },
        { path: '/userList', component: UserList }
    ]
})

UserList是用来登录成功后跳转的页面。

<script>
export default {
}
</script>
    
    <template>
    <div>
        <h1>用户管理</h1>
    </div>
</template>
    
<style scoped>
</style>

3、修改main.js

import { createApp } from 'vue'
import App from './App.vue'
import { router } from './router'

// import './assets/main.css'

// createApp(App).mount('#app')

const app = createApp(App)
// 注册路由
app.use(router)
app.mount('#app')

4、修改Login.vue

主要是添加点击事件和路由跳转

export default {
    data() {
        return {
            login: {
                username: '',
                password: ''
            }
        }
    },
    methods: {
        toLogin() {
            // 这里可以判断账号和密码是否为空。
           this.$router.push('/userList')
        }
    }
}

5、修改App.vue

router-view 显示与路由的页面。按创建顺序来,默认显示第一个。

类似html的iframe标签。

6、验证路由是否生效

点击登录,发现url产生变化,也发现页面跳转了,证明路由生效了。

1.6、指令复习

演示一个用户管理功能,用于快速学习vue为目的。

UserList.vue

<script>
export default {
    data(){
        return {
            userForm:{
                name: '',
                age: ''
            },
            userList: [{ name: '小明', age:22 },
                        { name: '大白', age:23 },
                        { name: '张三', age:24 }],
            delIds:[]
        }
    },
    methods:{
        addUser(){
            this.userList.push(this.userForm)
            this.userForm = {
                name: '',
                age: ''
            }
        },
        delUser(){
            let i = 0;
            for (const del of this.delIds.sort()) {
                this.userList.splice(del-i,1);
                i++;
            }
            this.delIds=[]
        }
    }
}
</script>
    
    <template>
    <div>
        <h1>用户管理</h1>
        <form action="">
            <input type="text" placeholder="用户名" v-model="userForm.name" >
            <input type="text" placeholder="年龄" v-model.number="userForm.age" @keyup.enter="addUser">
            <input type="button" value="添加" @click="addUser">
            <input type="button" value="删除" @click="delUser">
        </form>
        <ul>
            <li v-for="(user,index) in userList">
                <input type="checkbox" v-model="delIds" :value="index" />
                姓名:{{user.name}},
                年龄:{{user.age}}
            </li>
        </ul>
    </div>
</template>
    
<style scoped>
</style>

发现页面并不美观,下面我们引用UI组件库。

2、安装 UI 组件库

目前常用于VUE3的几款UI组件库:

适用于VUE3的几款高颜值UI组件库

2.1、安装Element Plus

# 在项目的根目录下
npm install element-plus --save

2.2、项目使用

main.js

import { createApp } from 'vue'
import App from './App.vue'
import { router } from './router'
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'

// import './assets/main.css'

// createApp(App).mount('#app')

const app = createApp(App)
// 注册路由
app.use(router)
app.use(ElementPlus)
app.mount('#app')

改造UserList.vue

<script>
export default {
    data(){
        return {
            userForm:{
                name: '',
                age: ''
            },
            userList: [{ name: '小明', age:22 },
                        { name: '大白', age:23 },
                        { name: '张三', age:24 }],
            delIds:[]
        }
    },
    methods:{
        addUser(){
            this.userList.push(this.userForm)
            this.userForm = {
                name: '',
                age: ''
            }
        },
        delUser(){
            let i = 0;
            for (const del of this.delIds.sort()) {
                this.userList.splice(del-i,1);
                i++;
            }
            this.delIds=[]
        }
    }
}
</script>
    
    <template>
    <div>
        <h1>用户管理</h1>
        <form action="">
            <input type="text" placeholder="用户名" v-model="userForm.name" >
            <input type="text" placeholder="年龄" v-model.number="userForm.age" @keyup.enter="addUser">
            <input type="button" value="添加" @click="addUser">
            <input type="button" value="删除" @click="delUser">
        </form>
        <ul>
            <li v-for="(user,index) in userList">
                <input type="checkbox" v-model="delIds" :value="index" />
                姓名:{{user.name}},
                年龄:{{user.age}}
            </li>
        </ul>
    </div>
</template>
    
<style scoped>
</style>

发现比之前好看多了。

3、axios

官网文档:http://www.axios-js.com/zh-cn/docs/vue-axios.html

3.1、axios是什么?

Axios 是一个基于 promise 的 HTTP 库,可以用在浏览器和 node.js 中。

功能与Ajax是一样的。都是请求后端接口获取数据。

3.2、安装axios

# 在项目的根目录下
npm install --save axios vue-axios

请求方法的别名:

为方便使用,官方为所有支持的请求方法提供了别名,可以直接使用别名来发起请求:

axios.request(config)
axios.get(url[, config])
axios.delete(url[, config])
axios.head(url[, config])
axios.post(url[, data[, config]])
axios.put(url[, data[, config]])
axios.patch(url[, data[, config]])

注意:在使用别名方法时, url、method、data 这些属性都不必在配置中指定。

3.3、项目使用

main.js

import { createApp } from 'vue'
import App from './App.vue'
import { router } from './router'
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
import axios from 'axios'
import VueAxios from 'vue-axios'

// import './assets/main.css'

// createApp(App).mount('#app')

const app = createApp(App)
// 注册路由
app.use(router)
app.use(ElementPlus)
app.use(VueAxios, axios)
app.mount('#app')

public添加测试数据userList.json

[
    { "name": "小明", "age": 22 },
    { "name": "大白", "age": 23 },
    { "name": "张三", "age": 24 }
]

改造UserList.vue

<script>
export default {
    created(){
        this.getUserList()
    },
    data(){
        return {
            userForm:{
                name: '',
                age: ''
            },
            userList: [],
            delIds:[]
        }
    },
    methods:{
        getUserList(){
        // 获取public下的test.json文件数据
        this.axios.get('/userList.json')
            .then(res => (
                //console.log(res)
                this.userList = res.data

            ))
            .catch(error => ( // 请求失败处理
                console.log(error)
            ))
        },
        addUser(){
            this.userList.push(this.userForm)
            this.userForm = {
                name: '',
                age: ''
            }
        },
        delUser(val){
            let i = 0;
            for (const del of this.delIds.sort()) {
                this.userList.splice(del-i,1);
                i++;
            }
            this.delIds=[]
        },
        selectObjs(val){
            this.delIds = [];
            for (const it of val) {
                this.delIds.push(this.userList.indexOf(it));
            }
        }
    }
}
</script>
    
    <template>
    <div>
        <h1>用户管理</h1>
        <el-form :model="userForm" :inline="true">
            <el-form-item>
                <el-input placeholder="用户名" v-model="userForm.name"  />
            </el-form-item>
            <el-form-item>
                <el-input placeholder="年龄" v-model.number="userForm.age" @keyup.enter="addUser" />
            </el-form-item>
            <el-form-item>
                <el-button type="primary" @click="addUser">添加</el-button>
                <el-button type="danger" @click="delUser">删除</el-button>
            </el-form-item>
        </el-form>
        <el-table :data="userList" stripe @selection-change="selectObjs">
            <el-table-column type="selection" width="55" />
            <el-table-column prop="name" label="名称" width="180" />
            <el-table-column prop="age" label="年龄" width="180" />
        </el-table>
    </div>
</template>
    
<style scoped>
</style>

4、组合式函数

为什么要使用setup组合?

鼠标跟踪器示例

<script setup>
import { ref, onMounted, onUnmounted } from 'vue'

const x = ref(0)
const y = ref(0)

function update(event) {
  x.value = event.pageX
  y.value = event.pageY
}

onMounted(() => window.addEventListener('mousemove', update))
onUnmounted(() => window.removeEventListener('mousemove', update))
</script>

<template>Mouse position is at: {{ x }}, {{ y }}</template>

但是,如果我们想在多个组件中复用这个相同的逻辑呢?我们可以把这个逻辑以一个组合式函数的形式提取到外部文件中

// mouse.js
import { ref, onMounted, onUnmounted } from 'vue'

// 按照惯例,组合式函数名以“use”开头
export function useMouse() {
  // 被组合式函数封装和管理的状态
  const x = ref(0)
  const y = ref(0)

  // 组合式函数可以随时更改其状态。
  function update(event) {
    x.value = event.pageX
    y.value = event.pageY
  }

  // 一个组合式函数也可以挂靠在所属组件的生命周期上
  // 来启动和卸载副作用
  onMounted(() => window.addEventListener('mousemove', update))
  onUnmounted(() => window.removeEventListener('mousemove', update))

  // 通过返回值暴露所管理的状态
  return { x, y }
}

下面是它在组件中使用的方式:

<script setup>
import { useMouse } from './mouse.js'

const { x, y } = useMouse()
</script>

<template>Mouse position is at: {{ x }}, {{ y }}</template>

组合式与普通的写法在于:

5、自定义指令

除了 Vue 内置的一系列指令 (比如 v-modelv-show) 之外。Vue 还允许你注册自定义的指令。

下面是一个自定义指令的例子,当一个 input 元素被 Vue 插入到 DOM 中后,它会被自动聚焦:

const focus = {
  mounted: (el) => el.focus()
}

export default {
  directives: {
    // 在模板中启用 v-focus
    focus
  }
}
<input v-focus />

上面是局部使用,如果我们想全局使用怎么做?

const app = createApp({})

// 使 v-focus 在所有组件中都可用
app.directive('focus', {
  /* ... */
})

6、Router进阶

官方文档:https://router.vuejs.org/

在上面我们只是简单使用Router来进行跳转。

实际上Router的功能很强大。

因为它是控制页面的跳转的,你完全可以在跳转前判断要不要跳转当前页面。

6.1、路由带参数

const routes = [
  // 动态字段以冒号开始
  { path: '/users/:id', component: User },
]

//接收参数
this.$route.params

6.2、嵌套路由

iframe标签里套iframe标签是一样的。

const routes = [
  {
    path: '/user/:id',
    component: User,
    // 请注意,只有子路由具有名称
    children: [{ path: '', name: 'user', component: UserHome }],
  },
]	

6.3、导航守卫

主要用来通过跳转前来处理请求。

使用 router.beforeEach 注册一个全局前置守卫:

const router = createRouter({ ... })

router.beforeEach((to, from) => {
  // to: 即将要进入的目标,
  // from: 当前导航正要离开的路由 
  // ...
  // 返回 false 取消跳转,这里也可以重定向到别的页面。
  return false
  // 将用户重定向到登录页面
  // return { name: 'Login' }
})

6.4、路由元信息

可以自定义一定属性在路由上,例如,某一个路由需要登录后才能访问。

const routes = [
  {
    path: '/posts',
    component: PostsLayout,
    children: [
      {
        path: 'new',
        component: PostsNew,
        // 只有经过身份验证的用户才能创建帖子
        meta: { requiresAuth: true }
      },
      {
        path: ':id',
        component: PostsDetail
        // 任何人都可以阅读文章
        meta: { requiresAuth: false }
      }
    ]
  }
]

例子:判断页面是否要登录才能访问

router.beforeEach((to, from) => {
  if (to.meta.requiresAuth && !auth.isLoggedIn()) {
    // 此路由需要授权,请检查是否已登录
    // 如果没有,则重定向到登录页面
    return {
      path: '/login',
      // 保存我们所在的位置,以便以后再来
      query: { redirect: to.fullPath },
    }
  }
})

7、axios进阶

1、主要对axios进行封装成工具来使用。

import axios from 'axios'
import { MessageBox, Message } from 'element-ui'
import store from '@/store'
import { getToken } from '@/utils/auth'

// create an axios instance
const service = axios.create({
  baseURL: process.env.VUE_APP_BASE_API, // api 的 base_url
  withCredentials: true, // 跨域请求时发送 cookies
  timeout: 5000 // request timeout
})

// request interceptor
service.interceptors.request.use(
  config => {
    // Do something before request is sent
    if (store.getters.token) {
      // 让每个请求携带token-- ['X-Token']为自定义key 请根据实际情况自行修改
      config.headers['X-Token'] = getToken()
    }
    return config
  },
  error => {
    // Do something with request error
    console.log(error) // for debug
    Promise.reject(error)
  }
)

// response interceptor
service.interceptors.response.use(
  /**
   * If you want to get information such as headers or status
   * Please return  response => response
  */
  /**
   * 下面的注释为通过在response里,自定义code来标示请求状态
   * 当code返回如下情况则说明权限有问题,登出并返回到登录页
   * 如想通过 XMLHttpRequest 来状态码标识 逻辑可写在下面error中
   * 以下代码均为样例,请结合自生需求加以修改,若不需要,则可删除
   */
  response => {
    const res = response.data
    if (res.code !== 20000) {
      Message({
        message: res.message,
        type: 'error',
        duration: 5 * 1000
      })
      // 50008:非法的token; 50012:其他客户端登录了;  50014:Token 过期了;
      if (res.code === 50008 || res.code === 50012 || res.code === 50014) {
        // 请自行在引入 MessageBox
        // import { Message, MessageBox } from 'element-ui'
        MessageBox.confirm('你已被登出,可以取消继续留在该页面,或者重新登录', '确定登出', {
          confirmButtonText: '重新登录',
          cancelButtonText: '取消',
          type: 'warning'
        }).then(() => {
          store.dispatch('user/resetToken').then(() => {
            location.reload() // 为了重新实例化vue-router对象 避免bug
          })
        })
      }
      return Promise.reject('error')
    } else {
      return res
    }
  },
  error => {
    console.log('err' + error) // for debug
    Message({
      message: error.message,
      type: 'error',
      duration: 5 * 1000
    })
    return Promise.reject(error)
  }
)

export default service

配置来源:https://github.com/PanJiaChen/vue-element-admin/blob/v4.0.0/src/utils/request.js

使用:

import request from '@/utils/request'

export function getList(query) {
  return request({
    url: '/demo/list',
    method: 'get',
    params: query
  })
}

8、项目发布

# 在项目的根目录下
npm run build

执行完成后,会在 Vue 项目下会生成一个 dist 目录

9、后话

写到这里,日常开发也差不多满足了

如果想更快理解,可以参照一些优秀项目来进行学习。

多练即可。

文章参考:

https://cn.vuejs.org/guide/introduction.html

https://zhuanlan.zhihu.com/p/482851017

https://www.runoob.com/vue3/vue3-tutorial.html

推荐后台管理模板:

https://vvbin.cn/doc-next/

http://blog.lgf196.top/ant-simple-pro-document/

https://gitee.com/codeZyZ_admin/vue3-composition-admin

https://gitee.com/panjiachen/vue-element-admin/tree/master/

标签:axios,const,进阶,app,router,学习,vue,vue3,import
来源: https://www.cnblogs.com/galenblog/p/16644181.html