目录
一. vue脚手架
1. 前端项目结构存在的问题
2. 如何解决
3. 使用脚手架的好处
4. 何时使用脚手架
5. 如何使用脚手架
二. 脚手架文件夹结构
1. 唯一完整的HTML页面被拆分为三部分: public/index.html
2. 页面组件: src/views文件夹下
3. 路由器对象: src/router/index.js
4. 全局组件或子组件: src/components文件夹下
三. ES6的模块化开发
1. 问题
2. 解决
3. 如何
四. 避免组件间样式冲突
1. 问题
2. 原理
3. 解决
五. watch+事件修饰符+防抖debounce
1. 问题
2. 解决
3. 何时
4. 如何
5. 结果
7. 解决
8. 问题
9. 解决
10. 问题
11. 解决
六. 懒加载
1. 问题
2. 原因
3 原理
4. 解决
七. 使用脚手架创建一个vue项目
扩展:this判断—8种指向
❣️ 总结:知识点提炼
【前文回顾】 vue中如何实现SPA 单页面应用_09
现代的前端项目结构非常复杂!如果任由什么人随意定义项目的文件夹结构,后果,项目与项目结构差异极大!即不便于维护,也不便于开发人员快速适应!
VUE官方出了一套标准化的vue项目结构!所有使用vue框架开发的项目都要遵守这个标准化项目结构!——脚手架
几乎所有用vue做的项目,文件夹结构几乎是完全一样的!开发人员可以非常快速的适应新项目!
今后无论学习任何框架,先找脚手架。
2步:
(1).下载并安装一个可以反复生成脚手架代码的命令行工具: (老母鸡)
a. 说明: 只要在电脑上安装一次,就可反复为多个不同的项目分别创建脚手架项目结构
b. 如何: 2步:
1). 先配置npm的国内淘宝镜像,从国内服务器下载和安装:快
2种选一种:
a. npm config set registry http://registry.npm.taobao.org
↓ ↓ ↓ ↓
npm 配置 设置 仓库
执行完之后,确认是否设置成功: npm config get registry
↓ ↓ ↓ ↓
npm 配置 获得 仓库
看到返回淘宝镜像,说明成功!
b. 备选方案: 如果上一步出错!可选择这一步:
npm i -g cnpm --registry=http://registry.npm.taobao.org
确认是否安装成功: cnpm -v
看到版本号说明成功!
2). 下载并安装命令行工具: vue/cli, 2种选一种
a. 用npm安装: npm i -g @vue/cli
npm 安装 全局 command line interface
install global 命令 行 接口
//如果说FEXIST错误,可进入出错提示中的路径,默认为:
C:\Users\登录操作系统的用户名\AppData\Roaming\npm\node_modules
删除@vue文件夹
b. 备选方案: 如果npm出错,可换成: cnpm i -g @vue/cli
看到: + @vue/[email protected],说明安装成功
(2). 用脚手架为这个项目创建一套标准化的vue项目结构:
a. 先找到要创建项目的文件夹:在操作系统中找到想要创建项目的文件夹目录,然后在地址栏中输入cmd,按回车
b. 输入vue create 自定义项目名
1). Vue CLI v4.5.8
? Please pick a preset: (Use arrow keys)
Default ([Vue 2] babel, eslint)
Default (Vue 3 Preview) ([Vue 3] babel, eslint)
> Manually select features
2). ? Check the features needed for your project: (Press
() Choose Vue version // 选择vue脚手架的版本
> (*) Babel // 转码器: 将时髦的ES6, ES7的语法,翻译为大多数浏览器都认识的ES5语法
() TypeScript
() Progressive Web App (PWA) Support // 渐进式Web应用程序
(*) Router // VueRouter,SPA应用的核心组件,即vue-router(vue路由组件)
() Vuex // vuex(vue的状态管理模式)
(*) CSS Pre-processors // CSS 预处理器(如:less、sass)—支持Scss语法,可选可不选
() Linter / Formatter // 代码风格检查和格式化工具(如:ESlint)要求比较严格,不建议选
() Unit Testing // 单元测试(unit tests)
() E2E Testing // e2e(end to end) 测试
3). ? Use history mode for router? (Requires proper server setup for index fallback in production) (Y/n) n
Vue的路由有两种模式:
hash模式:默认: #/相对路径 —— 不需要服务器端支持就可使用。
history模式:/相对路径 —— 需要服务器端配置首页重定向机制!
4). ? Where do you prefer placing config for Babel, ESLint, etc.? (Use arrow keys) In dedicated config files
> In package.json
5). ? Save this as a preset for future projects? (y/N) N
c. 成功: Successfully created project xzvue.
(3). 运行脚手架项目:
a. 删除项目中的.git文件夹(可保留,若你没使用vscode进行git版本(代码)管理,可删除)
b. vscode打开刚生成的脚手架项目文件夹
c. 在vscode中,右键点击package.json文件,选择在集成终端中打开
d. 在弹出的终端窗口中: 输入 npm run serve
如果遇到报错: 无法将“npm”项识别为 cmdlet...
可以右键点击我的电脑->属性->高级系统设置->环境变量->下方系统变量列表中->双击path->新建->C:\Users\用户名\AppData\Roaming\npm(其中用户名换成你当前操作系统登录时的用户名)
e. 成功: DONE Compiled successfully in 8922ms
f. npm run serve,启动了一个临时的服务器,保存vue编译后的所有网页。地址: App running at:
- Local: http://localhost:8080/
所以,在vscode中,按住ctrl点这个链接地址,打开浏览器
唯一完整的HTML页面(被拆成三分,运行时再组合起来)
(1). 问题: index.html中即没有
(2). 原因:
a. vue的作者认为, 在index.html中不应该包含任何js代码!
b. 作者认为,vue中一切都是组件,连
(3). 解决:
唯一完整的HTML页面被拆分的三部分为:index.html、App.vue、main.js
a. 原来index.html中的new Vue()等js代码,都集中保存在src/main.js文件中
b. 原来index.html中的
c. 在用npm run serve编译整个项目时:
1). 用App.vue中的
2). 将main.js中的new Vue()等js代码都重新引入回index.html页面中。
页面组件(项目中共有几个页面,就要包含几个页面组件)
(1). src/views文件夹下
(2). 问题:
a. 在js文件中写组件的template时,没提示,很痛苦!
b. css写哪儿?
(3). 解决: Vue中独创了一种新的文件格式: .vue文件
a. Vue中每个组件,都要创建为一个.vue文件
b. 每个.vue文件包含三部分内容:
1). 专门编写HTML代码片段的区域:
如果希望有提示,需要安装vscode的插件vetur
2). 专门编写组件对象的区域:
export default {
//页面组件的内容
}
3). 专门编写CSS样式的区域:
路由器对象: src/router/index.js,也包含路由字典routes和路由器对象router。
明明是router.js中需要用到index组件和details组件,但是我们却必须将index组件和details组件都引到index.html网页中!——乱
脚手架中采用了ES6的模块化开发!可以让模块与模块之间直接引用!——直观,简洁
比如说router.js中需要用到index组件和details组件,就可以直接引入,而不需要再绕到index.html网页引用
如何实现模块化开发,2步:
(1). 将所有组件都变成模块对象: (只有模块才能被引入,所以先要成为模块)
a. 默认: 一个不带js的.vue文件,默认就是一个模块对象。
有的.vue文件,是没有js的,而且有的.vue文件也没有css,比如有的.vue文件(组件)只有html(template)。一个模块对象不一定都有js或是css,只有html(template)的.vue文件就是一个vue默认的模块对象
b. 如果一个.vue文件中带有js组件对象,则必须用export default {}抛出模块对象后,才能让别人引入!
(2). 如果一个组件/模块内,需要用到另一个模块的内容,就可用import引入其它模块,为自己所用
import 自定义变量名 from "相对路径"
从指定路径的文件中
引入一个模块对象
保存在自定义的变量名中
扩展:.vue模块文件的后缀名可省略
使用import引入其他模块时,如果模块文件是.vue结尾,则可以省略.vue后缀名,如:import Detail from ”../views/detail.vue”,其中,.vue可省略;
如果如果模块文件是index.js,则引入时可以省略index.js,如:import router from “../router/index.js, 其中,index.js可省略。只要是引入模块,文件夹下的文件是index.js,都可以省略(只要文件夹下js文件是index.js,就可以省略)。可以查看学习node.js文件夹模块
关于何时使用 ../ 与 ./ —— 看有没有必要向上,如有必要使用 ../ 而平级的话则用 ./
在不同的页面组件中使用相同的选择器规定了不同的css样式,结果,只有其中一套css样式可以保留!发生了冲突!
所有组件的css代码,最终会被打包压缩为一个css文件。将来所有组件的css,其实是放在一个文件中的。如果一个文件中出现完全相同的两个选择器,则只有后一个才能生效!
2种:
(1). 自动化(不是万能, 效率低):
a.
运行结果:
About.vue
This is an about page
运行结果:
扩展:使用v-html绑定元素内容时,该元素内容的样式需要使用全局
元素进行设置
在单文件组件里,
scoped
的样式不会应用在v-html
内部,因为那部分 HTML 没有被 Vue 的模板编译器处理。如果你希望针对v-html
的内容设置带作用域的 CSS,你可以替换为 CSS Modules 或用一个额外的全局元素手动设置类似 BEM 的作用域策略。
参考vue官网v-html:https://cn.vuejs.org/v2/api/#v-html
如何实现一边输入,一边就执行操作!
使用vue中的监视函数watch
今后只要希望一个变量一发生变化,就能立刻执行一个我们自定义的任务!
组件对象中{
... ,
data(){
return {
变量:值
}
},
watch:{
变量(){
要执行的操作!
}
}
}
只要变量一发生变化,就自动调用watch中的同名函数
6. 问题
如何实现在文本框上点回车也能搜索?
@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="处理函数"
如果用户还没有输入完关键词,就去服务器频繁查找,既没必要,又浪费服务器端资源,降低效率!
防抖(debounce)
(1). 什么是: 必须等待用户操作停止后一段时间,才执行正式的操作!
(2). 何时: 今后只要希望阻止用户频繁操作向服务器发送请求时,都可以用防抖。
(3). 如何: 定时器
data(){
return {
... ,
timer:null
}
},
methods:{
查找方法(){
if(this.timer!=null){
clearTimeout(this.timer)
}
this.timer=setTimeout(()=>{
正式的查找操作
},等待时间)
}
}
单页面应用最大的问题: 首页加载极慢!
因为单页面应用默认在首次请求时,必须把所有页面组件都下载到客户端本地!
npm run serve时,vue脚手架会将所有.vue文件的代码都打包压缩到一个js文件中,再引入唯一完整的index.html文件中。所以,这个包含所有代码的js文件会很大!
懒加载,需要什么,才加载什么;不需要什么,就不加载!2种:
(1). 异步延迟加载(脚手架默认):
a. 什么是: 优先下载首页,其余页面组件,采用在底层异步延迟下载的方式,悄悄下载到客户端。
暂时不要把除首页之外的其它代码import进程序中!
在路由字典中定义,只有当用户访问到某个组件时,才动态引入这个组件。
src/router/index.js
import Vue from 'vue'
import VueRouter from 'vue-router'
import Index from "../views/Index"
Vue.use(VueRouter)
const routes = [
{
path: '/',
component: Index
},
{
path: '/details/:lid',
//暂时不要把Details.vue引入项目
//只有当用户访问到details时,才将Details组件引入项目中
//而且webpackChunkName:是在指示,将Details.vue文件单独打包压缩为一个文件。文件名为details
component: () => import(/* webpackChunkName: "details" */ '../views/Details.vue'),
props:true
}
]
const router = new VueRouter({
base: process.env.BASE_URL,
routes
})
export default router
b. 优点: 折中: 即不影响首页加载速度,又能保证将来切换页面时,只在客户端很快切换
c. 缺点: 万一用户不想看其余页面,也下载下来,有点儿浪费流量!
虽然不会在首屏下载details.js,但是却会在后台异步下载details.js,偷跑流量!
(2). 真正的懒加载:
彻底的懒加载⏬
a. 如果用户不访问其它页面,则根本一点儿都不下载其它页面的内容
b. 如何: 在vue脚手架中添加一个配置信息:
1). 在vue脚手架项目的根目录下创建vue.config.js
2). 在vue.config.js中添加以下固定配置信息,禁止提前下载其它组件
module.exports = {
chainWebpack: config => {
config.plugins.delete("prefetch")
//删除index.html开头的带有prefetch属性的link,不要异步下载暂时不需要的页面组件文件
},
}
c. 结果: 除首页之外的其它页面组件内容,一点都不提前下载。只有当用户点连接,访问到一个页面时,才临时下载这个页面组件的内容
d. 问题: 因为当用户访问页面时,临时去下载页面的内容,加载速度稍慢。
关于懒加载的疑问
你的疑惑
有人会问,只有当用户点连接,访问到一个页面时,才临时下载这个页面组件的内容,这跟多页面应用(都是下载后,才能拿过来看)不就没有什么区别了吗?
个人理解首先,下载的是个片段,而非整个页面,这比多页面应用的请求的整个页面小多了,其次,彻底的懒加载只需要下载一次,保存到客户端的,今后可以反复看,以前的多页面应用是不行的,多页面应用是不缓存的。所以,临时下载虽然慢了一点,但比起多页面应用来说优势还是很明显的
我们先来介绍一下,今后vue脚手架项目中必用的请求工具axios,是如何安装、配置和并引入组件的
安装和配置axios:
(1). 脚手架默认不带axios
(2). 安装: npm i -save axios
安装在当前项目内部
(3). 配置:
a. 在main.js中, new Vue()之前就要配置
b. 引入axios模块
import axios from "axios" // node_modules中
c. 配置axios的基础路径:
axios.defaults.baseURL="http://服务器端接口的基础地址"
d. 问题: 几乎所有组件中都要用到axios
前提: 无论是new Vue(),还是Vue.component(), 还是export default {},其实本质都是Vue类型的一种子对象
解决: 所以axios应该放在Vue类型的原型对象中!
Vue.prototype.axios=axios
(4). 使用: 在任何一个组件的任何一个位置,都可用:
this.axios.get/post(...).then(result=>{ ... result.data ... })
脚手架项目完整的文件夹结构,如下图所示:
vue项目各组件源码如下:
◼️ public/index.html 唯一完整的html页面
<%= htmlWebpackPlugin.options.title %>
◼️ src/App.vue 唯一的根组件(汇总所有组件)
◼️ src/components/MyHeader.vue 页头组件——全局组件
◼️ src/views/Home.vue 主页组件
我的第一个脚手架项目!
我的用户昵称:{{ uname }}
用户ID:{{ uid }}
◼️ src/views/About.vue 关于页组件
methods: {
search() {
alert("欢迎访问CSDN!");
window.location.href = `https://blog.csdn.net/sunyctf`
},
},
};
◼️ src/main.js 项目入口js文件
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import axios from "axios"
import MyHeader from "./components/MyHeader.vue"
Vue.component("my-header",MyHeader);
axios.defaults.baseURL="http://localhost:8080";
// 将axios类库添加到vue的原型对象中,这样每个页面都可以使用
Vue.prototype.axios=axios;
Vue.config.productionTip = false
new Vue({
router,
render: h => h(App)
}).$mount('#app')
◼️ src/router/index.js 路由器文件
import Vue from 'vue'
import VueRouter from 'vue-router'
import Home from '../views/Home.vue'
Vue.use(VueRouter)
const routes = [
{
path: '/',
name: 'Home',
component: Home
},
{
path: '/about',
name: 'About',
// route level code-splitting
// this generates a separate chunk (about.[hash].js) for this route
// which is lazy-loaded when the route is visited.
// 懒加载
component: () => import(/* webpackChunkName: "about" */ '../views/About.vue')
}
]
const router = new VueRouter({
routes
})
export default router
◼️ src/assets/css/home.css 主页样式文件
/* 解决避免组件间样式冲突的方法:
* 1). 每创建一个组件,都在组件的唯一父元素上,定义一个专门的class名(尽量和组件名相同)
* 2). 在
18. watch+事件修饰符+防抖:
(1). 希望变量一变化就自动执行一项操作时:
data(){
return { 变量: 值 }
},
watch:{
变量(){
要执行的操作
}
}
(2). 事件修饰符:
@事件.13 按回车时才执行
@事件.stop 阻止冒泡
@事件.prevent 阻止默认行为
(3). 防抖:
data(){
return {
... ,
timer:null
}
},
methods:{
查找方法(){
if(this.timer!=null){
clearTimeout(this.timer)
}
this.timer=setTimeout(()=>{
正式的查找操作
},等待时间)
}
19. 懒加载:
(1). 异步延迟下载:
src/router/index.js
// 不要import Details from "../views/Details"
const routes=[
...
{
path:"/details/:lid",
component: () => import(
/* webpackChunkName: "details" */
'../views/Details.vue'
),
props:true
]
(2). 彻底懒加载:
项目根目录创建vue.config.js
module.exports={
chainWebpack:config=>{
config.plugins.delete("prefetch")
//删除index.html开头的带有prefetch属性的link,不要异步下载暂时不需要的页面组件文件
},
}
【后文传送门】 vue中如何使用http代理解决跨域问题_11
如果这篇【文章】有帮助到你,希望可以给【青春木鱼】点个赞,创作不易,相比官方的陈述,我更喜欢用【通俗易懂】的文笔去讲解每一个知识点,如果有对【前端技术】感兴趣的小可爱,也欢迎关注❤️❤️❤️【青春木鱼】❤️❤️❤️,我将会给你带来巨大的【收获与惊喜】!