Vue #脚手架安装 #脚手架文件结构 #ES6模块化开发 #项目流程 #懒加载 #代理跨域 #组件样式冲突 #watch #防抖

一. 脚手架

             vue官方定义了一套标准的项目结构,vue项目都要基于这套标准结构开发
1.安装可以反复创建脚手架项目的命令行工具
   a.npm默认是国外的,访问慢而且不稳定 
   		1)淘宝镜像:npm config set registry http://registry.npm.taobao.org
   		2)备选方案:npm i -g cnpm --registry=http://registry.npm.taobao.org  (cnpm -v 查看版本)
   b.用npm或cnpm安装反复生成脚手架项目的命令行工具:
   		1). 用npm安装: npm  i   -g @vue/cli     //如果说FEXIST错误,可进入出错提示中的路径,默认为: C:\Users\登录操作系统的用户名\AppData\Roaming\npm\node_modules 删除@vue文件夹
   		2). 如果npm出错,可换成: cnpm i -g @vue/cli
   c.验证vue/cli是否安装成功: vue -V	(看到版本号说明安装成功)  //i安装 g全局
2.用脚手架工具,创建一个项目的标准文件夹结构的副本:
	a.找到要创建的文件夹位置;
	b.在当前位置,地址栏输入cmd,在当前路径打开命令行窗口
	c.命令行运行:
	(1)vue.create xxx;
	(2)选择版本:请选择预设:(1)默认vue2  (2)默认vue3  (3)手工选择功能

在这里插入图片描述

	(3)选择你需要的项目功能:

在这里插入图片描述

	(4)选择一个版本 :

在这里插入图片描述

	(5)是否启用history作为路由:

在这里插入图片描述

	(6)你想要在哪里放配置:

在这里插入图片描述

   (7)为将来的项目保存一个预设:
   

在这里插入图片描述

	(8)安装成功:npm run serve 运行脚手架

在这里插入图片描述

二. 脚手架文件结构

问题:所有JS文件都堆在一个JS文件夹里,管理和使用非常混乱
解决:真实的项目,都是把不同用途的JS文件,分别放在不同的文件夹中分类保存

在这里插入图片描述

脚手架的项目结构:
(1) public文件夹 ----   开发过程中,很少修改
	a).单页面应用唯一完成的HTML页面
	b).img文件夹
	c).第三方开发压缩过的css或者js源代码
(2) src文件夹  ----    自己编写的一切源代码
	a).assets文件夹:自己开发的一些通用的工具代码
	b).components文件夹:包含所有的全局组件或子组件片段
	c).router文件夹:包含路由器对象和路由字典的文件夹
	d).views文件夹:包含所有当作页面使用的组件
	e).App.vue:保存唯一完成HTML页面的<div id="app">以及内部和页头和<router-view>
	f).main.js:保存整个项目唯一的newVue({})代码
	
vue文件:
(1)问题: 传统的使用js文件创建组件的方式,有两个问题: 
	a. HTML内容是写在模板字符串中,既没有提示,又没有颜色区分!极其不便于代码编写和纠错!
	b. 在js文件中,就没有编写css内容的位置!
	(2). 解决: vue脚手架中首创了一种新的文件格式: .vue文件,同时包含: 
	a. <template></template>: 专门包含当前组件的HTML内容,既有提示,又有颜色区分!极其有利于代码的编写和纠错
	b. <script></script>专门包含当前组件的js对象
	c. <style></style>专门包含当前组件的CSS代码
	所以,将来vue脚手架项目中,只要创建一个组件(全局组件,子组件,页面组件),一律都要创建为.vue文件。

三. ES6的模块化开发

包含一组功能或数据的一个整体
旧网页中:必须将所有的js文件和对象先统一引入到页面的内存中。然后再分配

在这里插入图片描述

解决:如果一个功能向使用另一个功能内容,直接引入,不需要经过HTML页面统一引入

在这里插入图片描述

如何在脚手架中使用模块化开发: 
	(1). 如果一个模块文件的内容想被别人引入并使用,必须使用: 
	export default { 组件内容 }
	抛出一个模块
	(2). 如果一个模块想使用另一个模块抛出的内容,必须使用: 
	import 别名 from "要引入的模块文件的相对路径"
	结果: 在当前模块中使用"别名",就等效于使用引入的模块内容
特殊: 如果组件内容非常简单,没有任何js代码,只有HTML和css代码,则不用export default { ... },默认也是一个模块

在这里插入图片描述
在这里插入图片描述

四. 项目的实现

1.准备:
	问题:vue脚手架天生不带axios,所以用axios必须单独安装
	解决:项目文件夹 npm i -save axios   结果:node_modules文件夹多一个axios文件夹
	如何:main.js中new Vue()之前 
	引入:import axios from "axios"  
	vue原型对象添加:Vue.prototype.axios=axios
	统一配置基础路径属性:axios.defaults.baseURL="http://服务器端同一域名"

在这里插入图片描述

结果:任何位置发送axios请求,只写/相对路径即可,不用反复填写域名

在这里插入图片描述

在这里插入图片描述

(1). 将图片和第三方文件放入public文件夹下
(2). 所有页面都需要的基础的css文件内容,应该放在App.vue中的<style>里。
		因为App.vue中包含<router-view>,所以,放在App.vue中的css样式,是所有页面共享的
实现首页: 
	(1). 删除src/views/Home.vue,新建Index.vue,其中包含三部分内容: 
	a. <template>: 首页主体内容的HTML代码
	比如: 从旧项目public下index.html中复制首页的主体内容html代码(<main></main>及其内容),粘贴到新项目src/views/Index.vue中的<template>标签内。
	b. <style>: 首页所需的css样式
	比如: 从旧项目public下css/index.css文件中,全选复制所有css代码,粘贴到新项目src/views/Index.vue中<style>标签内
	(2). 必须去路由器对象(src/router/index.js)中配置首页的路由字典: 
	import Index from "../views/Index"

	const routes = [
  		{
    		path: '/',
    		component: Index
  		},
	(3). 实现首页商品数据的绑定: 
	a. 在首页组件的mounted中使用axios请求来首页的6个商品数据:
	b. 在首页组件中添加data(){ return { }},并在data中定义四个变量: 
		p1:{price:0}, p2:{price:0}, p3{price:0}, others:[]
	   问题: 因为在axios请求回来之前,vue就要使用p1,p2,p3中的price调用toFixed()函数,所以p1,p2,p3中的price不能是空的!所以,p1,p2,p3中都要有一个price:0属性,临时占位。
	c. 在首页组件的mounted中将请求回来的result.data中的商品分别放到p1,p2,p3和others变量中
		this.p1=result.data[0];
		this.p2=result.data[1];
		this.p3=result.data[2];
		this.others=result.data.slice(3);
3. 实现点首页商品,跳转到详情页查看详情:
	(1). 先在src/views文件夹下,删除About.vue,新建Details.vue,其中也包含三部分内容: 
	a. <template>: 包含详情页的HTML内容
	比如: 从旧项目public/product_details.html中,复制详情页的主体部分HTML内容,粘贴到新项目src/views/Details.vue中<template>标签中
	b. <style>: 包含详情页的css样式
	比如: 从旧项目public/css/product_details.css中,复制详情页的所有css代码,粘贴到新项目src/views/Details.vue中<style>标签中
	c. <script>: 包含详情页的组件对象内容
	(2). 去新项目src/router/index.js中引入详情页.vue,并配置路由字典
	import Details from "../views/Details"

	const routes = [
	  {...},
	  {
    	path:"/details/:lid",
    	component: Details,
    	props:true
  	  }
	注释:{ path:"/about", ... }
	(3). 在Details.vue中mounted()中发送axios请求,获得指定编号的商品的详细信息: 
	a. 获得地址栏中的参数值: props:[ 'lid' ] //复习vue第四天的SPA应用
	b. 在mounted中发送axios请求,获得指定编号的商品信息
	(4). 将获得的商品详细信息绑定到页面上: 
	a. 先创建data(){ return {} },并在data中定义页面所需的变量
	b. 在mounted中将获得相应结果中的商品对象的属性,赋值给data中的变量
	c. 在Details.vue中51行开始,绑定商品的title, subtitle, price, promise四个属性
	(5). 回到Index.vue中,为每个商品上的"查看详情"按钮,绑定详情页地址

	坑: 服务器端返回的商品对象.href属性地址,还是旧项目的地址格式: 
		product_details.html?lid=5
	解决: 将旧地址按=切割,取第二部分商品编号,再和/details/拼接为vue需要的地址
		<router-link :to="`/details/${p1.href.split('=')[1]}`";
	(6). 为了防止axios请求回来之前p1.href.split()报错,应该: 
		data(){
			return {
				p1:{ price:0, href:"" }, 
				p2:{ price:0, href:"" },
				p3:{ price:0, href:"" },
				others:[]
				//others中不用属性占位也不会报错,是因为others中元素个数为0时,v-for一次都不执行!就不会读到页面中的p.href.split()。所以,数组中不用占位,只有单个对象绑定时,才用属性占位。
			}
		}
	

五. 懒加载

 单页面应用的致命问题: 首屏加载极慢。因为单页面应用默认必须在首次请求时,把所有页面组件都下载到客户端本地
 npm run serve时,vue脚手架会将所有.vue文件的代码都打包压缩到一个js文件中,再引入唯一完整的index.html文件中。所以,这个包含所有代码的js文件会很大
懒加载,2: 
	(1). 异步延迟加载(脚手架默认):
	a. 暂时不要把除首页之外的其它代码import进程序中!
	b. 在路由字典中定义,只有当用户访问到某个组件时,才动态引入这个组件。 

在这里插入图片描述

问题: 虽然不会在首屏下载details.js,但是却会在后台异步下载details.js,偷跑流量
彻底的懒加载: 
	a. 如果用户不访问其它页面,则根本一点儿都不下载其它页面的内容
	b. 如何: 在vue脚手架中添加一个配置信息: 
		1). 在vue脚手架项目的根目录下创建vue.config.js
		2). 在vue.config.js中添加配置信息,禁止提前下载其它组件
		module.exports={
  			chainWebpack:config=>{
    			config.plugins.delete("prefetch")
    			//删除index.html开头的带有prefetch属性的link,不要异步下载暂时不需要的页面组件文件
  			},
		}
	vue.config.js

在这里插入图片描述

结果: 除首页之外的其它页面组件内容,一点都不提前下载。只有当用户点连接,访问到一个页面时,才临时下载这个页面组件的内容
问题: 因为当用户访问页面时,临时去下载页面的内容,加载速度稍慢。

六. http-proxy 代理跨域

问题: 
	(1). CORS: 优点: 仅服务器端修改即可; 缺点: 必须知道客户端的具体IP地址
	(2). JSONP: 优点: 不需要知道客户端具体IP地址; 缺点: 需要客户端和服务器端都作出调整!
	(3). 如果服务器端觉得CORS也不好用,JSONP也不好用,干脆就没有做跨域!单靠前端能否跨域?
解决: 利用vue脚手架中自带的http-proxy代理程序来跨域访问。详细信息可查看官方文档: https://cli.vuejs.org/config/#devserver-proxy
在vue脚手架配置文件(vue.config.js)中,添加一个新的配置项
	module.export={
		... ... ,
		devServer: {
    	  proxy: {
      	    '/api': { //为所有服务器端接口起一个别名前缀,为了和vue脚手架中其它页面的路由地址区分
        	  target: `http://服务器端接口地址统一前缀`,
        	  changeOrigin: true, //跨域
              pathRewrite: {
				//因为真实的服务器端地址中是不包含/api的,所以
                '^/api' : '' //应该将程序中的/api删除(替换为空字符串),再和target中的基础路径拼接起来作为发送到服务器的最终请求地址。
              }
            }
          }
       }
	}
	(2). 在main.js中,axios的baseURL就不能写真实的服务器地址,应该写devServer中定义的所有服务器端地址的别名前缀: 
	axios.defaults.baseURL="/api"
	(3). 在组件内使用axios发送请求时,依然使用接口的相对地址就可以: this.axios.get("/index")
this.axios.get("/index")  
		↓axios会将baseURL和"/index"拼接
	this.axios.get("/api/index")
	所有↓带有/api前缀的路径都会交给devServer程序处理
	  devServer —— 不使用ajax,也能发送http请求的程序
		↓先将相对路径中的/api去掉
       /index
	    ↓再和提前配置好的这是服务器地址target拼接
	http://localhost:5050/index
		↓向真实的服务器接口地址发送请求
      devServer接到响应结果
		↓
      返回给axios.then(result=>{})继续处理
	整个过程因为没有用到ajax,所以不受浏览器同源策略的限制。

七. 组件间样式冲突

脚手架项目在运行时会将所有组件的js打包为一个js文件,也会将所有组件的css打包为一个css文件。不同组件中的css最终会放在一个文件中并存!同名的选择器之间一定会发生冲突!
(1).解决: <style scoped>
	a. 原理: 自动给组件以及组件内所有元素添加随机自定义属性,用不同的自定义属性名来区分不同组件中的元素。
	b.问题: 
		1). 对每个HTML元素都加随机自定义属性,效率低
		2). 不一定总是有效的!
	c. 示例: 使用<style scoped>避免组件间样式冲突
(2) 好的解决: 为每个组件起一个专门的class名
	a. 如何: 21). 在定义组件时,组件的唯一父元素上就要提供一个唯一的class2). 凡是这个组件下的选择器,都要以这个组件的唯一父元素上的class作为开头!
	b. 优点: 不需要vue多做任何处理就能避免样式冲突,效率高
	c. 示例: 使用class名避免组件间样式冲突: 

八. watch + 事件修饰符 +防抖

如何实现一边输入 一边就执行操作
解决: 使用vue中的监视函数watch
何时: 只要希望一个变量一发生变化,就能立刻执行一个我们自定义的任务
如何: 
	组件对象中{
		... ,
		data(){
			return {
				变量:}
		},
		watch:{
			变量(){
				要执行的操作!
			}
		}
	}

在这里插入图片描述

只要变量一发生变化,就自动调用watch中的同名函数
问题: 如何实现在文本框上点回车也能搜索?
解决: <input @keyup="search">
@keyup的问题: 
	(1). 当@keyup和watch同时存在时,执行的操作可能重复执行两遍: 内容变化,变量变化,watch执行;又因为触发了keyup,所以事件处理函数也执行。
	(2). 除了按字母和回车键之外,按键盘上其它无关的按键也会触发搜索操作 特别没必要!
	(3). 应该只有按照回车键时才能执行搜索操作

解决: 就要用vue中的事件修饰符: 
	(1). 事件修饰符: 对传统的DOM事件对象中常用方法和属性的简写。
	(2). 想判断键盘按键的编号: 
	a. DOM: if(e.keyCode==13)
	b. vue中: @keyup.13 //只有按在13号键上才执行操作
	(3). 其它事件修饰符常用的操作: 
	a. 停止冒泡: 
		1). DOM: e.stopPropagation()
		2). vue中: @事件名.stop="处理函数" 
	b. 阻止默认行为: 
		1). DOM: e.preventDefault()
		2). vue中: @事件名.prevent="处理函数"
10. 问题: 如果用户还没有输入完关键词,就去服务器频繁查找,既没必要,又浪费服务器端资源,降低效率!
解决: 防抖(debounce)
	(1). 什么是: 必须等待用户操作停止后一段时间,才执行正式的操作!
	(2). 何时: 今后只要希望阻止用户频繁操作向服务器发送请求时,都可以用防抖。
	(3). 如何: 定时器

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值