第1章 简介

我们在学习新技术的时候,习惯于将官方文档先过一遍,将全部的知识点全部掌握之后,再进行项目实战,但是因为太多都是概念的知识,学习过程枯燥乏味,很少有人能坚持下来。

所以我在想,怎么改变这种现象?以我个人的经验来说,过多深究官方文档,反而将自己陷入知识点的海洋之中,抓不到重点,往往水过鸭背,因为学了没有真正应用,不久之后就会忘记,我的意思是,不用看什么官方文档,以终为始,不用管自己到底会不会,直接上手开发项目,根据当前的需求,去学习对应的知识点,比如现在你要生成一个 Vue3.0 项目,那么你可能只需要去学一下Vite对应的知识点就好了,不用去学Vue3.0中父子组件应该怎么传值?比如你要学习开发一个登陆页面,那你就需要去看Element-Plus应该怎么引入?如果你所学并不能为当下所用,那将毫无意义。

其实在你一步一步完成真实项目的过程中,就一直在学习Vue3.0的知识点了。

本书计划将 Vue3.0 的知识过一遍,所以一些 Vue2.0 就需要的环境配置就不再过多说明,只会提到 Vue3.0 开发环境配置相关的内容,用到的技术有 Vue3.0+Vite+TypeScript+Element-Plus+Less

第2章 开发环境配置

2.1 新建项目

Vite官方文档 中,已经提供了很多预设的模板,这里因为只关注当前使用的技术,所以其他模板并不详细说明,使用 Vite 生成 Vue3.0 项目模板,如果是使用 JaveScript 进行开发,使用 vue ,如果是使用 TypeScript 进行开发,使用 vue-ts ,具体命令如下所示:

# npm 6.x
npm init vite@latest my-vue-app --template vue
# npm 7+, 需要额外的双横线
# 如果是使用JaveScript开发使用vue
npm init vite@latest my-vue-app -- --template vue
# 如果是使用JaveScript开发使用vue-ts
npm init vite@latest my-vue-app -- --template vue-ts

打开chrome,就会显示项目模板的内容,如下图所示:

2.2 Chrome 91版本以上跨越问题

第3章 Vue3.0基础知识

3.1 Router

3.2 Comand

3.3 Porps

3.4 Emit

3.5 Vuex

3.5.1 computed

computed主要用于涉及到视图更新的处理,比如用户名username的更新,刷新后,右上角用户名没有赋值成功。在App.vue中已经添加了getUserInfo的网络请求,但是在右上角上赋值显示失败了。

使用方式如下所示,并没有触发视图更新:

const username = store.state.userInfo.username

触发视图更新:

improt { useStore } from 'vuex'
const store = useStore()
const username = computed(() => {
    return store.state.userInfo.username
})

userInfo敲定刷新后的获取策略

  1. 通过在App.vue中重新发起请求获取用户信息

    问题:1.登录页面刷新因为没有token会报错,解决可以加上判断,但是代码很难看。

     2.每个组件中都需要watch监听usrInfo,很繁琐。
    
  2. 登录后将用户信息保存在localStorage,刷新后通过vuex中获取

    问题: 1.如果更新了用户信息,刷新后获取的还是旧的数据

     2.在getters.ts中判断数据为空就重新发起网络请求,获取用户信息,但是因为异步的原因,数据并没有同步。
    
  3. 登录后触发commit,然后在mutations.ts中,将用户信息保存到localStorage,刷新后通过vuex获取。

    问题: 1.需解决刷新后还是旧数据的问题,那就需要更新后,通过commit更新localStorage中的用户信息

  4. 最终确定以方式3实现:

    使用方式:

    
     import { useStore } from 'vuex'
    
      let userInfo = store.getters.userInfo
    

在ZHeaderArea.vue中的 let userInfo = computed(() => { return store.state.userInfo })

改为getter获取就报错




### 3.5.2 watch

`watch`用于监听数据有变化触发,用于需要对数据进行操作时使用,比如个人中心,刷新后,使用`computed`方式`userInfo`没有成功获取,原因是`<template>`上并没有使用userInfo进行关联。

```tsx
     let userInfo = store.state.userInfo
     setUserInfoListValue(userInfo)
     watch(
         () => store.state.userInfo,
         (newValue, oldValue) => {
             userInfo = newValue
             setUserInfoListValue(userInfo)
         }
     )
     function setUserInfoListValue(info: any) {
         userInfoList.forEach((item: any) => {
             for (var key in info) {
                 if (item.prop === key) {
                     item.content = info[key] ? info[key] : '--'
                 }
             }
         })
     }

3.5 Vite.config.ts

3.5.1 如何设置路径别名

在项目中,因为组件或者ts文件引入,需要指定路径,如果文件层级很深,在开发中就会变得很繁琐,使用别名可以有效的解决这个问题。

第一步,需要在vite.config.ts文件中加上,如下所示:

const path = require('path')
export default defineConfig({
  resolve: {
    alias: {
      '@': path.resolve(__dirname, './src')
    }
  }
  ......
})

第二步,需要在tsconfig.json文件中加上,如下所示:

{
  "compilerOptions": {
    
    ......
    
    "baseUrl": "./",
    "paths": {
      "@/*":["./src/*"]
    }
  }

此时,就可以在项目中使用@了。

第4章 搭建项目框架

4.1 Container布局容器

4.1 左侧菜单栏实现

  1. 左侧菜单栏,实现过程中遇到了一个问题,那就是el-aside的宽度默认是300px,项目中需求是200px,这个不难,只需要在中设置width=“200px"就可以解决了,然后如果要实现展开和收缩,就需要设置,而它的宽度需要单独设置的 ,设置为200px,实现展开和收缩功能,收缩时宽度变为60px,但是还是200px,其实要实现联动,只需要动态设置width的值就好了,但是实现左侧菜单栏,我们通常是单独抽成组件来使用的,这样要联动就很麻烦,其实要实现也是可以的,使用props就好了,但我还是想着有没有更好的方法,有什么办法能够动态设置的宽度?

    因为去掉的宽度属性发现,实现的效果是很理想的,后来发现只需要设置width为auto即可

  2. 左侧菜单栏,如何使用组件递归实现?

  3. el-menu折叠时为何不显示二级菜单?

    当菜单栏折叠时,发现首页的图标没有显示,实现的代码如下所示:

    <el-menu-item v-if="!item.childrens" :index="`${String(index)}`" :route="item.index">
    	<template #title>
    		<div class="zws-aside-menu-item">
    			<i :class="`zws-aside-menu-item-iconSetting iconfont ${item.icon}`"></i>
    			<span>{{ item.title }}</span>
    		</div>
    	</template>
    </el-menu-item>
    

    之前的项目没有这个问题是因为不是使用collapse这个属性实现的,而是动态设置宽度,200和60切换达到的效果。查看官方文档的案例,发现这个写法,当折叠时,是显示图标的,如下所示:

    <el-menu-item index="4">
    	<i class="el-icon-setting"></i>
    	<span slot="title">导航四</span>
    </el-menu-item>
    

    然后按照官网的写法,将