vue-spa单页应用程序

mac2025-12-06  13

Vue全家桶

回顾:

1 ES6—为Vue服务的

2 vue基础语法 + axios

3 前后端分离

4 node之npm命令

安装jquery:npm install jquery卸载jquery:npm uninstall jquery-g 全局安装:安装到c的用户的目录-D 开发环境的依赖安装-S 生产环境的依赖安装切源 nrm

使用软件:Visual Studio Code + Node.js + vue

软件安装包:https://pan.baidu.com/s/1Vd75XR0gAZ3YR32FbHpA2g 提取码:57rc

自己写的纯vue前端代码:https://github.com/kedaya-github/vue_front


0 前置知识

0.1 ES6-模块化

0.1.1 什么是模块化

模块化就是把代码进行拆分,方便重复利用。类似java中的导包:要使用一个包,必须先导包。

而JS中没有包的概念,换来的是 模块。

模块功能主要由两个命令构成:export和import。

export命令用于规定模块的对外接口,import命令用于导入其他模块提供的功能。

0.1.2 export

比如我定义一个js文件:hello.js,里面有一个对象:

const util = { sum(a,b){ return a + b; } }

我可以使用export将这个对象导出:

const util = { sum(a,b){ return a + b; } } export util;

当然,也可以简写为:

export const util = { sum(a,b){ return a + b; } }

export不仅可以导出对象,一切JS变量都可以导出。比如:基本类型变量、函数、数组、对象。

当要导出多个值时,还可以简写。比如我有一个文件:user.js:

var name = "jack" var age = 21 export {name,age}

省略名称

上面的导出代码中,都明确指定了导出的变量名,这样其它人在导入使用时就必须准确写出变量名,否则就会出错。

因此js提供了default关键字,可以对导出的变量名进行省略

例如:

// 无需声明对象的名字 export default { sum(a,b){ return a + b; } }

这样,当使用者导入时,可以任意起名字

0.1.3 import

使用export命令定义了模块的对外接口以后,其他 JS 文件就可以通过import命令加载这个模块。

例如我要使用上面导出的util:

// 导入util import util from 'hello.js' // 调用util中的属性 util.sum(1,2)

要批量导入前面导出的name和age:

import {name, age} from 'user.js' console.log(name + " , 今年"+ age +"岁了")

但是上面的代码暂时无法测试,因为浏览器目前还不支持ES6 的导入和导出功能。除非借助于工具,把ES6 的语法进行编译降级到ES5,比如Babel-cli工具

我们暂时不做测试,大家了解即可。

上课代码:

// 方式一 : 未来在html页面引入的时候,引入名字必须是util // const util = { // add(a,b){ // return a+b // } // } // export util; // 方式二: 未来在html页面引入的时候,引入名字必须是util // export const util = { // add(a,b){ // return a+b // } // } export const add = { add(a,b){ return a+b } } export const increament = { add(a,b){ return a+b } } // 方式三:未来在html页面引入的时候,引入名字随意 export default { add(a,b){ return a+b }, increament(a,b){ return a+b }, }

1 SPA-Vue企业级开发模式

1.1 什么是SPA?

SPA(Single Page Application):单页面应用程序,是一种前端的开发技术,是现在前、后端分离下的一种产物。

传统的网站

​ 我们传统的网站是由很 多个独立的页面 组成的,当我们点击页面中的 a 标签时,就会向服务器发送一个新的请求,然后下载另一个页面显示,跳转时是页面之间的跳转。

SPA

SPA(单页面应用程序),顾名思议,整个网站中只有一个页面,在这个页面中会加载很多个不同的组件,当我们点击按钮时,并不会打开一个新的页面,而是还在当前的页面中切换显示不同的组件。

1.2 SPA 的优、缺点

优点

1、减轻服务器的压力:一个网站只有一个页面,只需要从服务器加载一次

2、并且把大量操作都放到了浏览器中去完成

3、前、后端完成分离,使服务器只需要提供同一套 JSON 数据接口,就可以同时满足WEB端、桌面端、手机端等不同的前端设备

4、而且前端只关注前端、后端只操作数据,各司其职

缺点

1、首屏加载速度可能会很长

2、SEO(搜索引擎优化)不友好,爬虫数据时什么也抓不到

3、页面复杂度提高、开发难度加大

1.3 使用 Vue 开发 SPA

Vue全家桶有哪些技术?

我们可以使用 Vue 框架来开发 SPA,开发时使用的技术:

1、使用 Vue Cli 脚手架工具快速构建项目目录结构、开发环境、部署

2、使用 Vue-Router 实现路由,实现组件之间的切换

3、使用 Vuex 实现状态数据的管理

4、使用 axios 发送 AJAX 和服务器通信

1.4 *.vue 文件–SPA中的组件

在使用 Vue 开发 SPA 时,SPA 是由很多个 Vue 的组件组成的,每个组件就是一个 .vue 文件。

每个 .vue 文件中都由三部分组件:HTML、CSS、JS,并且:

1、html:所有的 html 代码必须要写在 <template>html代码</template> 标签中

2、css:所有的 css 代码写在 <style> css样式表<style> 标签中

3、js:所有 js 代码写在 <script>js代码</script> 标签中

以下是一个* .vue 文件中的内容:

<template> <div> <h1> Hello World ! 我是 {{ tome }} </h1> <input type="button" @click="sayHi" value="sayHi"> </div> </template> <style> body{ background-color: #EEE; } h1 { font-size: 30px; } </style> <script> export default { data(){ return { name:'tom' } }, methods:{ sayHi(){ alert("Hi") } } } </script>

1.5 SPA 中的 Vue

SPA 中的 Vue 和我们之前学习过的 Vue 的用法大体上是一致的,不过也有一些不一样的地方需要注意一下:

我们之前使用 vue 时,都是在 data 中定义数据,而 data 是一个属性类型,如:

new Vue({ data:{ name:'tom', age:10 } })

在 spa 中,每个 .vue 文件是一个 Vue 的组件,在组件中 data 必须是一个函数,而且不能使用 new Vue 创建新的 Vue 对象,因为整个 SPA 中只有一个 Vue 对象:

export default { data(){ return { name:'tom' } } } 使用 import 引入组件

我们之前当要引入一个JS文件或者组件时需要使用 script 标签,如:

<script src='Pagination.js'></script>

而在 spa 中需要使用 es6 提供的 import 来引入:

import Pagination from "Pagination.vue"

2 使用 Vue CLI构建项目

Vue 提供了一个 Vue CLI 的工具可以让我们快速的搭建起一个 SPA 的项目来。

2.1 官方网站

官方文档:https://cli.vuejs.org/zh/

2.2 安装

首先要确定自己的电脑上安装了 Node.js 8.9 或更高版本。

然后,我们就可以使用 npm 来安装 vue/cli :

npm install -g @vue/cli

安装之后,我们可以在命令行中使用 vue 指令查看安装的版本:

vue --version

2.3 创建一个项目

我们可以使用下面的命令来创建一个 SPA 的项目:

vue create 项目名称

创建项目时,会提示我们选择项目中需要使用的组件,我们可以使用默认的配置,也可以自己手动选择需要加载的组件。

手动选择组件

勾选需要安装的组件:

​ babel:将ES6的语法转成浏览器可以执行的低版本js语法

​ Router:(必须)路由

​ Vuex: 可选

使用路由的 history 模式:

把配置写到 package.json 文件中:

不保存本次的配置:

项目创建成功。

2.4 目录介绍

我们写的代码都在 src 目录中:

2.5 启动项目

安装成功之后,我们可以进行使用以下指令启动项目:

cd 项目名 // 进入项目目录 npm run serve // 启动项目

启动之后我们可以在浏览器中访问欢迎页面:

2.6 初始组件 App.vue

项目启动之后会最先运行 main.js 文件:

main.js

import Vue from 'vue' import App from './App.vue' import router from './router' import store from './store' Vue.config.productionTip = false new Vue({ router, // 装载 vue-router store, // 装载 vuex render: h => h(App) // 渲染 App 组件 }).$mount('#app')

在 main.js 文件中会

1、引入 vue 、vue-router、vuex 框架包

2、引入 App 组件

3、创建 Vue 对象并且装载 vue-router , vuex

4、渲染第一个组件:App.vue

所以我们运行之后看到的页面就是 App.vue 组件的内容。

3. Vue-Router

在 SPA 中,网站内容的变换实际上的组件的切换,为了方便的实现组件间的切换,Vue 框架引入了 vue-router 的个工具来实现多个组件之间的切换。

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

3.1 配置路由

在使用 vue-router 之前,我们需要先配置访问的路径与要显示的组件的对应关系。

我们需要在 router.js 文件中进行配置。

router/index.js

默认配置了两个路由:

1、当访问 / 时,显示 Home 组件

2、当访问 /about 时,显示 about 组件

import Vue from 'vue' import VueRouter from 'vue-router' import Home from '../views/Home.vue' // Vue对象的静态方法 Vue.use(VueRouter) // 有一个页面,在此处就需要配置一个路由 const routes = [ { path: '/', name: 'home', component: Home }, { path: '/about',// 就是url,就是未来访问的路径 name: 'about',// 随意 component: () => import( '../views/About.vue') }, { path: '/list',// 就是url,就是未来访问的路径 name: 'list',// 随意 component: () => import( '../views/List.vue') } ] const router = new VueRouter({ mode: 'history', base: process.env.BASE_URL, routes }) export default router

说明:

1、about 组件的写法是延迟加载:在访问 /about 路径时才会加载该组件,这样可以提高首屏显示速度

2、/* webpackChunkName: "about" */ 的意思是将这个组件添加到 about 这个组中,当访问 about 这个组件时就会添加所有 about 这个组中的组件

3.2 路由切换按钮

当我们定义好路由之后,我们就可以在页面中添加按钮跳转到相应的路由,有两种跳转方法:

1、在 HTML 中使用 router-link 标签(相当于a标签)

2、在 JS 中使用 router-push 实现跳转(相当于 location.href )

3.2.1 router-link 标签

我们可以在页面中使用 router-link 标签来制作可以跳转的按钮(相当于 a 标签):

<div id="nav"> <router-link to="/">Home</router-link> | <router-link to="/about">About</router-link> </div>

说明:to 属性用来指定点击按钮时要切换到的路由

3.2.2 router.push

在 JS 中我们可以使用 this.$router.push 实现跳转。

login(){ console.log( '登录成功' ) // 跳转到 / this.$router.push('/主页面.vue') }

3.3 组件容器

我们在使用 vue-router 时,除了要配置路由之后,最重要的是,我们还需要在页面中使用 router-view 标签来指定组件显示的位置:

<template> <div id="app"> <div id="nav"> <router-link to="/">Home</router-link> | <router-link to="/about">About</router-link> </div> <!-- 组件显示的容器 --> <router-view/> </div> </template>

这时所有的路由组件都会显示在 router-view 标签所在的位置上:

1、默认显示路由配置中的第一个路由,也就是 / 路由

2、当切换路由时,也是在这个标签的位置上切换路由

因为我们在 router.js 文件的路由是这样配置的:

routes: [ // 配置路由的数组 { path: '/', // 访问路径 name: 'home', // 路由名称 component: Home // 对应的组件 }, { path: '/about', name: 'about', component: () => import(/* webpackChunkName: "about" */ './views/About.vue') } ]

第一个是 home 路由,所以默认显示的就是 Home 组件的内容:

3.4 案例:添加一个页面

1、首先在 views 目录下创建 Hello.vue 组件

views/Hello.vue

<template> <div> <input @click="sayHello" type="button" value="sayHello"> </div> </template> <style> body { background-color: #eee; } </style> <script> export default { methods:{ sayHello(){ alert('Hello ~') } } } </script>

注意:HTML的代码必须要写在一个根标签中。

2、配置路由

在 router.js 文件中的 routes 数组中添加一个 hello 路由

router.js

routes: [ ... { path: '/hello', // 路径 name: 'hello', // 名称 component: () => import('./views/Hello.vue') // 加载的组件 } ]

3、添加切换按钮

在 App.vue 页面中添加跳转到 /hello 的按钮

App.vue

<div id="nav"> <router-link to="/">Home</router-link> | <router-link to="/about">About</router-link> | <router-link to="/hello">hello</router-link> </div>

添加之后保存,保存之后页面会自动刷新:

点击 hello 按钮,就会在 router-view 标签的位置上切换到 Hello 组件:

3.5 页面组件与功能组件

组件分为两种:页面组件 和 功能组件。

页面组件

用来构建独立页面的组件,保存在 views 目录中,页面组件中可以包含多个功能组件。

功能组件

我们可以将页面中一些独立的小功能制作成组件,这些组件可以被页面组件引入使用,比如:翻页、时间插件等,功能组件保存在 components 目录中,这些组件不能独立显示,只能被包含在一个页面组件中使用。

页面组件和功能组件的关系:(每个页面就是一个页面组件,每个页面中可以包含多个功能组件)

3.6 使用功能组件

系统中默认有一个 HelloWorld 组件:

如果要在页面中使用这个组件需要先使用 import 引入该组件,然后在使用标签使用该组件。

修改 Hello.vue 页面:

views/Hello.vue

效果:

3.7 路由参数

我们在定义路由时经常需要为路由添加一些参数,比如当点击一件商品进入商品详情页时需要把商品的ID传到页面中。

我们可以使用以下语法定义带参数的路由:

{ path: '/hello/:id', name: 'hello', component: () => import('./views/Hello.vue') }

这时当我们访问 /hello/1 , /hello/tom 等路径时都会匹配 Hello 组件。

如果我们希望只匹配数字做为参数,这时可以使用正则表达式来限制匹配的类型:

id 参数必须是数字:

{ path: '/hello/:id(\\d+)', name: 'hello', component: () => import('./views/Hello.vue') }

在组件中可以使用 this.$router.params 来接收传过来的所有的参数。

比如在 Hello.vue 组件中可以这样接收 id 这个参数:

export default { ... created(){ // 打印接收的 id 参数 alert(this.$route.params.id) } ... }

3.8 嵌套路由(很重要!!!!!!了解)

有时一个页面中可能还会嵌套子页面,比如在 hello 页面中,可能还会有 hello tom 和 hello jack 两个子页面,这时我们就可以通过在定义路由时使用 children 数组来定义嵌套路由。

router.js

{ path: '/hello', name: 'hello', meta: { title:'hello' }, component: () => import('./views/Hello.vue'), children: [ // /hello/tom { path: "tom", name: "hello-tom", component: () => import('./views/HelloTom.vue') }, // /hello/jack { path: "jack", name: "hello-jack", component: () => import('./views/HelloJack.vue') } ] }

然后在 Hello.vue 页在中再添加两个按钮和一个 router-view 设置子页面的位置:

views/Hello.vue

<router-link to="/hello/tom">Hello Tom</router-link> | <router-link to="/hello/jack">Hello Jac</router-link> <hr> <router-view></router-view>

效果:当点击 Hello Tom 和 Hello Jack 按钮时,会切换嵌套组件

嵌套组件关系图:

4 vue-axios

官方推荐我们在 vue 中使用 axios 发送 AJAX 的请求。

在开发 SPA 时,我们需要把 axios 集成进来,我们可以使用 vue-axios 这个包。

文档地址:https://www.npmjs.com/package/vue-axios

4.1安装

使用的方法非常的简单:

1、先安装

npm install axios

4.2 使用-局部引入使用

1、局部引入和使用,在*.vue页面中使用

<script> // @ is an alias to /src // import HelloWorld from '@/components/HelloWorld.vue' import { axios } from "axios"; axios.defaults.baseURL="http://localhost:8080" export default { name: 'home', data(){ return { users:[] } }, created(){ axios.get("/user").then(res => { this.users = res.data }) } } </script>

4.2 使用-全局引入使用

1、全局引入

安装之后需要修改 main.js ,在文件中引入并使用 axios 包:

main.js

import Vue from 'vue' import App from './App.vue' import router from './router' import store from './store' // @ is an alias to /src // import HelloWorld from '@/components/HelloWorld.vue' import axios from 'axios' // axios.defaults.baseURL="http://localhost:8080" axios.defaults.baseURL='http://localhost:8080' Vue.prototype.$http = axios Vue.config.productionTip = false new Vue({ router, store, render: h => h(App) }).$mount('#app')

2、使用

引入了之后,我们就可以在项目中使用以下三种方法来使用 axios 了:

export default { name: 'home', data(){ return { users:[] } }, created(){ this.$http.get("/user").then(res => { this.users = res.data }) } } </script>

4.2 案例:通过 axios 请求数据

1、在 Home.vue 中显示数据

Home.vue

在初始化时执行 AJAX 获取数据:

<script> // @ is an alias to /src // import HelloWorld from '@/components/HelloWorld.vue' import { axios } from "axios"; axios.defaults.baseURL="http://localhost:8080" export default { name: 'home', data(){ return { goods:[] } }, created(){ axios.get("/goods").then(res => { this.goods = res.data }) } } </script>

将数据绑定到页面:

<ul> <li v-for="(v,k) in goods" :key="k"> {{v.goods_name}} ¥ {{v.price}} <hr> </li> </ul>

效果:

5. Vuex

5.1 什么是 Vuex?

Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。

Vue 是由数据驱动的,也就是说每个组件的状态都是由数据决定的,比如一个元素的显示与隐藏就是它的两种状态,这两种状态在 vue 中都会由一个数据来管理。

比如,下面的 img 标签的显示与隐藏由 isShow 这个数据决定,当 isShow 为 true 时显示,为 false 时隐藏:

<template> <div> <img v-if="isShow" src="../assets/logo.png"> </div> </template> <script> export default { data(){ return { isShow: true } }, ... } </script>

也就是说现在这个元素的状态由 isShow 这个数据来决定。

在实际工作中,我们有时会遇到这样一种情况:我们需要在一个组件中操作另一个组件中元素的状态,比如我们需要在 b.vue 这个组件中设置 a.vue 中元素的显示状态,但 vue 是不允许跨文件操作数据的:

这时,我们就可以把需要同时被多个组件操作的数据提取出来,由 状态管理器 统一进行管理,在这种模式下,所以的组件都可以操作由 状态管理器 统一管理的数据:

有了状态管理器,我们就可以在所有组件中管理 a.vue 中图片的显示状态。

总结:Vuex(状态管理器),就是可以把需要多个组件同时管理的数据管理起来,让所有组件可以共同操作以改变一个组件的状态 。

5.2 使用 Vuex

5.2.1 定义状态数据与方法

在使用 Vux 时,首先我们需要先定义状态数据和操作它的方法。

使用 Vuex 时,最重要的两部分是:state 和 mutation。

state:保存所有组件公共的数据。(数据部分)

mutation:保存操作公共数据的方法。(函数部分)

在最开始构建项目时,如果在安装时勾选了 vuex 组件,那么就已经安装好了 vuex。

在 store.js 文件中定义 state 和 mutation :

在 store.js 文件中定义 state(数据)和mutations(操作数据的函数):

import Vue from 'vue' import Vuex from 'vuex' Vue.use(Vuex) export default new Vuex.Store({ state: { isShow: false }, mutations: { changeShow(){ this.state.isShow = !this.state.isShow } }, actions: { } })

5.2.2 使用状态数据

在 store.js 文件中定义好状态数据之后,我们就可以在页面中使用 $store.state.状态数据名称 来读取状态数据的值了:

views/Home.vue

<template> <div class="home"> <img v-if="$store.state.isShow" alt="Vue logo" src="../assets/logo.png"> <HelloWorld msg="Welcome to Your Vue.js App"/> </div> </template>

5.2.3 调用mutation

当我们要修改状态数据时,我们可以使用 this.$store.commit('方法名') 来调用状态函数来修改状态数据:

views/Home.vue

<script> ... export default { ... created(){ ... // 每5秒改变一次状态 setInterval(()=>{ this.$store.commit('changeShow') }, 5000) } } </script>

5.3 案例:登录、退出

store.js 中定义登录、退出按钮的状态:

import Vue from 'vue' import Vuex from 'vuex' Vue.use(Vuex) export default new Vuex.Store({ // 要管理的公共的数据(数据) state: { isShow:true, isLogin: false }, // 定义修改这个数据的方法(方法) mutations: { changeShow(){ this.state.isShow = !this.state.isShow }, // 如果要设置参数,第一个参数必须是 state ,代表 state 对象 // 第二个参数才是我们自定义的参数 setLogin(state, value){ state.isLogin = value } }, actions: { } })

App.vue 中根据 isLogin 显示按钮:

<template> <div id="app"> <div id="nav"> <router-link to="/">Home</router-link> | <router-link to="/about">About</router-link> | <router-link to="/hello">Hello</router-link> | <router-link to="/goods/23">商品页</router-link> | <template v-if="$store.state.isLogin"> <input @click="logout" type="button" value="退出"> </template> <template v-else> <router-link to="/login">登录</router-link> | </template> </div> <router-view/> </div> </template> <script> export default { created(){ if(localStorage.getItem('token')) this.$store.commit('setLogin', true) }, methods:{ logout(){ localStorage.removeItem('token') this.$store.commit('setLogin', false) console.log( this.$store.state.isLogin ) } } } </script> <style> #app { font-family: 'Avenir', Helvetica, Arial, sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; text-align: center; color: #2c3e50; } #nav { padding: 30px; } #nav a { font-weight: bold; color: #2c3e50; } #nav a.router-link-exact-active { color: #42b983; } </style>

Login.vue 在登录成功时修改 isLogin 的值

<template> <div> <input type="text" v-model="username"> <input type="password" v-model="password"> <input @click="login" type="button" value="登录"> </div> </template> <script> export default { data(){ return { username:'', password:'' } }, methods:{ login(){ if(this.username = 'abc' && this.password == 'abc') { localStorage.setItem('token', 'afdsa324#!#REfds~~') // 修改登录状态 this.$store.commit('setLogin', true) // 跳转到首页 this.$router.push('/') } } } } </script>

效果:登录、退出时按钮状态发生变化:

最新回复(0)