Vue.js 项目工程化+路由(一)

660 阅读7分钟

20220513录屏

3 Vue项目工程化

什么是Vue项目工程化开发?

Vue HTML项目—中小型项目,比如单页、留言板、访客预约、简单的企业网站。

HTML开发的痛点:

​ 在很多 Vue 项目中,我们使用 Vue.component 来定义全局组件,紧接着用 new Vue({ el: '#container '}) 在每个页面内指定一个容器元素。

  • 全局定义 (Global definitions) 强制要求每个 component 中的命名不得重复 elementui el-button 模块化
  • 字符串模板 (String templates) 缺乏语法高亮,在 HTML 有多行的时候,需要用到丑陋的 \ 没有语法提示
  • 不支持 CSS (No CSS support) 意味着当 HTML 和 JavaScript 组件化时,CSS 明显被遗漏
  • 没有构建步骤 (No build step) 限制只能使用 HTML 和 ES5 JavaScript,而不能使用预处理器,如 Pug (formerly Jade) 和 Babel

单文件组件:

​ 文件扩展名为 .vuesingle-file components (单文件组件) 为以上所有问题提供了解决方法,并且还可以使用 webpack 或 Browserify 等构建工具。

Vue项目工程化开发:

​ 首先,Vue的思想:利用数据及组件来驱动。工程化就是为了让前端开发能够“自成体系”,从模块化组件化规范化三个方面体现:

1 **模块化:**代码划分为一系列职责单一,高度解耦且可替换的模块。===》可维护及扩展性强

2 组件化:页面或功能进行组件化分割并开发。===》单文件组件,多人开发,互不干扰。

3 **规范化:**项目开发规范化可操作性强。 ===》好的规范会直接影响到开发质量和效率。

  • 目录结构的制定
  • 编码规范 HTML JS CSS 附件 命名 前后端接口规范
  • 文档规范
  • 组件管理

Vue项目 工程化与html开发的区别

  • 由原来直接html页面开发,变成在vue的单文件组件以源码开发。
  • 引入组件、js库或者vue插件、CSS等资源,要以模块化的思想,来import和export。万物皆可模块化
  • 要预先定义组件和url的关系,即路由,来实现页面的跳转、重定向、前进或后退。
  • 增加了由源代码vue===>编译===》打包成html再发布的过程 webpack工具

相同点

  1. 都是在写html css js
  2. 最后 部署 都是 html结构

创建Vue项目

  1. 利用官网的VueCLI 脚手架工具 - 安装工具

    1. 安装nodejs 或将hbuilderX插件中的node和npm设置成环境变量 path

      查看命令 node -v 和 npm -v

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kc62sgna-1652420150626)(Vue.js培训笔记/image-20220512142001229.png)]

    nodejs.cn/

    1. 新建vue-cli目录
    2. npm i vue-cli
    3. 查看vue 版本
    4. vue create 项目名 or vue ui 使用可视化工具
  2. 利用HbuilderX 新建Vue项目

    调整HbuilderX npm的仓库源 改成国内淘宝镜像

    cd E:\tools\HBuilderX\plugins\npm

    查看命令:npm config get registry

    调整命令:npm config set registry registry.npm.taobao.org

Vue目录解析 (以HbuilderX构建为例)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GRx6tpqX-1652420150627)(Vue.js培训笔记/image-20220510135320314.png)]

node_modules文件夹:用来存放用包管理工具下载安装的包的文件夹。ElementUI、Axios等工具都放到这里。

public文件夹: 公共资源 index.html 是将来打包后的入口文件。

src 源代码文件夹: 我们的开发工作主要在此进行。

bable.config.js: bable.js:该工具为了把高版本的ES6编译成低版本的,以保证浏览器兼容性。该文件是其配置文件。

package.json: 是Vue项目的整体配置文件,一般包括有项目启动、打包命令,声明依赖包等。npm install 构建项目时,必不可少的文件。

package-lock.json:是当 node_modules 或 package.json发生变化时自动生成的文件。这个文件主要功能是确定当前安装的包的依赖,以便后续重新安装的时候生成相同的依赖,而忽略项目开发过程中有些依赖已经发生的更新

postcss.config.js:postcss:是一个利用JS插件来对CSS进行转换的工具

README.md 说明书

vue源代码目录

assets文件夹:静态文件夹,存放静态资源,如img、css、fonts等。

components:组件文件夹,存放.vue的单页面公共组件。

App.vue: 项目的根(root)组件,项目的运行主入口。

main.js:项目的核心文件,首先执行的文件。

运行项目

运行Vue项目 == 执行 npm run serve 指令

  1. HbuilderX 运行->运行到浏览器/内部浏览器 自动执行 ‘npm run serve’ 注:需在打开vue文件
  2. 选中项目,右键外部命令 ‘npm run serve’
  3. 打开windows的CMD或power shell控制台,CD到项目目录,运行npm run serve (需要在计算机中安装nodejs环境,否则npm无法执行,或者将HbuilderX插件中的npm目录加到系统的环境变量Path中)

package.json命令:

"scripts": {
 "serve": "vue-cli-service serve",
 "build": "vue-cli-service build"
},

serve:利用vue-cli-service来启动服务

build:利用vue-cli-service来进行打包

停止项目

crtl+c Y 或 crtl+c 两次

App.vue 单文件组件 源码分析

单文件应用:SPA single page applcation

<template>
  <div id="app">
    <img alt="Vue logo" src="./assets/logo.png">
    <HelloWorld msg="Welcome to Your Vue.js App"/>
  </div>
</template>

<script>
import HelloWorld from './components/HelloWorld.vue'

export default {
  name: 'app',
  components: {
    HelloWorld
  }
}
</script>

<style>
#app {
  font-family: 'Avenir', Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>

单文件组件,是以.vue为后缀的文件。

由三个闭合标签构成:

template: html代码,即组件中的template属性,里面存放的时html标签。

script:js代码,定义组件的name,实例化Vue对象,并导出export default到项目中

style: css代码

单文件的含义,即用一个vue文件,来表示一个组件。

import export 语法 es6中 模块化

导出语法:

export {}

用大括号包围导出的变量名,多个以逗号分隔。

let v = '你好';
const num = 200;
let arr = [
	1, 3, 5, 7, 8
]
let obj = {
	username: '王小二',
	age: 20,
	fun: function() {
		console.log(this.username + this.age);
	}
}

let clog = function(info) {
	console.log("导出的信息" + info);
}

export {
	v,
	clog,
	num,
	arr,
	obj
}

导入语法:

import {clog,v,obj} from './export.js' 

导入用大括号接收导出的成员名,多个以逗号分隔。 from:文件的路径,同级目录前加"./"

import {clog,v,obj} from './export.js'
export default {
name: 'app',
components: {
HelloWorld
},
mounted(){
	  clog('哈哈哈啊')
	  console.log(v);
	  obj.fun()
}

}
</script>

使用 import ** from ** 和 import ‘路径’ 还有 import {a, b} from ‘模块标识’ 导入其他模块

export default 1个

export default obj
import obj from './export.js'

import 此处接收的变量名,可以自定义。

创建一个NavList的组件

  1. 创建template html结构
  2. export default 导出
  3. 在App.vue中导入
  4. 在App.vue的template中书写自定义组件标签名

打包项目

运行Vue项目 == 执行 npm run build指令

思考&&测试:如何创建组件之间的链接跳转?

下面用a链接的方式:

<a href="components/HelloWorld.vue"></a>

不可行的

4 vue-router路由

vue-router安装

  • 安装

在HbuilderX的项目管理器项目目录上,右键执行“使用命令行窗口打开所在目录”,在终端里输入:

npm view vue-router versions  可以仓库的所有版本
npm install vue-router@3.2.0 
或者 npm install vue-router@3  安装大版本3下的最高版本

官网的命令,默认时安装Vue-router4的版本,会报错。npm install vue-router@4

安装完毕后,在node_modules文件夹里会有一个vue-router文件夹。index.js里export导出了

  • 引入
main.js

import Vue from 'vue'
import App from './App.vue'

// 引入vue router
import VueRouter from 'vue-router'

// 使用router
Vue.use(VueRouter)

Vue.config.productionTip = false

import HelloWorld from './components/HelloWorld.vue'
import NavList from './components/NavList.vue'
import Header1 from './components/header.vue'

// 定义路由
const router = new VueRouter({
	routes: [{
			path: '/helloworld',
			component: HelloWorld
		}
	] 
})

// 挂载属性
new Vue({
	router,
	render: h => h(App),
}).$mount('#app')
  • 使用-组件的渲染
<template>
  <div id="app">
	<router-link to="/helloworld">
		hellowrld的跳转 
	</router-link>
	<!--  渲染区域 -->
	<router-view></router-view>	
  </div>
</template>

<script>
export default {
  name: 'app',
}
</script>

<style>

</style>

命名路由

有时,通过一个名称来标识一个路由显得更方便,特别是在链接一个路由,或者是执行一些跳转时。可以在创建Router实例时,在routes配置中给某个路由设置名称

const router = new VueRouter({
  routes: [
    {
      path: '/user/:userId',
      name: 'user',
      component: User
    }
  ]
})

要链接到一个命名路由,可以给 router-linkto 属性传一个对象:

<router-link :to="{ name: 'user', params: { userId: 123 }}">User</router-link>

这跟代码调用 router.push() 是一回事

router.push({ name: 'user', params: { userId: 123 }})

这两种方式都会把路由导航到 /user/123 路径

命名路由的常见用途是替换router-link中的to属性,如果不使用命名路由,由router-link中的to属性需要设置全路径,不够灵活,且修改时较麻烦。使用命名路由,只需要使用包含name属性的对象即可

[注意]如果设置了默认子路由,则不要在父级路由上设置name属性

<div id="app">
  <p>
    <router-link to="/" exact>index</router-link>
    <router-link :to="{ name: 'foo1' }">Go to Foo</router-link>
    <router-link :to="{ name: 'bar' }">Go to Bar</router-link>
  </p>
  <router-view></router-view>
</div>
const Home = { template: '<div>home</div>' }
const Foo = { template: `
  <div>
    <p>
      <router-link :to="{ name: 'foo1' }" exact>to Foo1</router-link>
      <router-link :to="{ name: 'foo2' }" >to Foo2</router-link>
      <router-link :to="{ name: 'foo3' }" >to Foo3</router-link>  
    </p>
    <router-view></router-view>
  </div>
  ` }
const Bar = { template: '<div>bar</div>' }
const Foo1 = { template: '<div>Foo1</div>' }
const Foo2 = { template: '<div>Foo2</div>' }
const Foo3 = { template: '<div>Foo3</div>' }
const routes = [
  { path: '/', name:'home', component: Home },
  { path: '/foo', component: Foo ,children:[
    {path:'',name:'foo1', component:Foo1},
    {path:'foo2',name:'foo2', component:Foo2},
    {path:'foo3',name:'foo3', component:Foo3},
  ]},
  { path: '/bar', name:'bar', component: Bar },
]

声明式导航与编程式导航

除了使用<router-link>创建a标签来定义导航链接,还可以借助router的实例方法,通过编写代码来实现

【router.push(location)】

​ 应用场景:需要用js来控制跳转,比如用户登录后,跳转到首页。

想要导航到不同的 URL,则使用 router.push 方法。这个方法会向 history 栈添加一个新的记录,所以,当用户点击浏览器后退按钮时,则回到之前的 URL。

当点击 <router-link> 时,这个方法会在内部调用,所以说,点击 <router-link :to="..."> 等同于调用 router.push(...)

声明式                 编程式
<router-link :to="...">     router.push(...)

在@click中,用 r o u t e r 表 示 路 由 对 象 , 在 m e t h o d s 方 法 中 , 用 t h i s . router表示路由对象,在methods方法中,用this. router表示路由对象,在methods方法中,用this.router表示路由对象

该方法的参数可以是一个字符串路径,或者一个描述地址的对象。例如:

// 字符串
router.push('home')
// 对象
router.push({ path: 'home' })
// 命名的路由
router.push({ name: 'user', params: { userId: 123 }})
// 带查询参数,变成 /register?plan=private
router.push({ path: 'register', query: { plan: 'private' }})

router.replace(location)

router.push 很像,唯一的不同就是,它不会向 history 添加新记录,而是跟它的方法名一样 —— 替换掉当前的 history 记录

声明式                           编程式
<router-link :to="..." replace>     router.replace(...)        

router.go(n)

这个方法的参数是一个整数,意思是在 history 记录中向前或者后退多少步,类似 window.history.go(n)

// 在浏览器记录中前进一步,等同于 history.forward()
router.go(1)
// 后退一步记录,等同于 history.back()
router.go(-1)
// 前进 3 步记录
router.go(3)
// 如果 history 记录不够用,就静默失败
router.go(-100)
router.go(100)

项目页面的路由

index / 根路径 404

routes中组件定义方式:

  1. 使用import 把组件导入,然后component值为导入的名。

    import HelloWorld from './components/HelloWorld.vue'
    component: HelloWorl
    
  2. 直接设置在component的值为一个匿名(箭头)函数

    component: () => import('@/pages/index')
    
const routes = [
	{
		path: '/',
		component: () => import('@/pages/index')
	}, {
		path:'*',
		component:()=> import('@/pages/404')
	},
]

根路径

设置根路径,需要将path设置为’/’

  <p>
    <router-link to="/">index</router-link>
    <router-link to="/foo">Go to Foo</router-link>
    <router-link to="/bar">Go to Bar</router-link>
  </p>

const routes = [
  { path: '/', component: Home },
  { path: '/foo', component: Foo },
  { path: '/bar', component: Bar },
]

但是,由于默认使用的是全包含匹配,即’/foo’、‘/bar’也可以匹配到’/‘,如果需要精确匹配,仅仅匹配’/',则需要在router-link中设置exact属性

  <p>
    <router-link to="/" exact>index</router-link>
    <router-link to="/foo">Go to Foo</router-link>
    <router-link to="/bar">Go to Bar</router-link>
  </p>

const routes = [
  { path: '/', component: Home },
  { path: '/foo', component: Foo },
  { path: '/bar', component: Bar },
]

router路由分离

  1. src目录下建立router文件夹 router文件夹里新建index.js到访
  2. index.js 引入vue、vue-router、使用、配置路由规则、实例化vue-router
  3. 导出实例化对象
  4. 在main.js里引入
router/index.js

/*index.js 引入vue vue-router、使用、配置路由规则、实例化vue-router */
import Vue from 'vue'
import VueRouter from 'vue-router';
// 使用router
Vue.use(VueRouter)
// 配置路由规则
const routes = [
	{
		path: '/',
		component: () => import('@/pages/index')
	}, {
		path:'*',
		component:()=> import('@/pages/404')
	},
]
const router = new VueRouter({
	routes
})
export default router

main.js

import Vue from 'vue'
import App from './App.vue'
// 引入router下的index.js 只写目录 默认会导入目录下index.js
import router from './router'

Vue.config.productionTip = false


// 挂载属性
new Vue({
	router,
	render: h => h(App),
}).$mount('#app')

路由课堂练习

router-link练习

pages:

​ 首页 index 关于我们 about 新闻中心 news 公司产品 product 联系我们 contact

comonents:

​ 头部 header 底部 footer

this.$router.push 练习

pages:

​ 首页 index 登录页 login