项目目录结构介绍
项目创建完成之后,我们会看到bingo_web项目其实是一个文件夹,我们进入到文件夹内部就会发现一些目录和文件,我们简单回顾一下里面的部分核心目录与文件。
├─node_modules/# node的包目录,项目运行的依赖包存储目录,package.json和package-lock.json文件中会自动记录了这个目录下所有的包以及包的版本信息,
├─public/# 静态资源目录,项目中的静态资源(css,js,图片等文件)放在这个文件夹
├─src/# 主开发目录,要开发的客户端代码文件(单文件组件,css样式、工具函数等等)全部在这个目录下
├─assets/# 静态资源存储目录,与public目录作用类似。
├─router/# 路由存储目录,是我们创建项目的时候,如果选择安装vue-router,就自动会生成这个目录。
├─views/# 组件页面存储目录,就是浏览器中用户看到的页面内容,views往往会加载并包含components中的组件进来
├─components/# 组件存储目录,就是浏览器中用户看到的页面的一部分内容。
├─App.vue
├─main.js
└─style.css
├─index.html
└─package.json # 如果node_modules没有,但是有package.json,则可以在终端下,通过npm install进行恢复node_modules所有内容。
2.3、项目执行流程图
要在Vue.js项目中指定域名和端口,你通常需要配置Vue CLI提供的
devServer
,而不是直接在
defineConfig
里面指定域名和端口。
devServer
配置通常用于开发环境,它允许你定义开发服务器的参数,比如端口号、代理设置等。不过,如果你想要在生产环境中配置一个特定的域名和端口,这通常需要在部署到服务器时,通过服务器配置(例如Nginx或Apache)来实现,而不是在Vue CLI的配置中直接设置。
如果你的目的是为了开发环境,想要Vue CLI开发服务器运行在www.bingo.com域名和80端口,你可以试着修改
vue.config.js
文件(如果文件不存在,你需要手动创建这个文件):
首先,确认你的电脑上
hosts
文件已经将
www.bingo.com
指向了
127.0.0.1
(本地开发环境)。
然后,编辑
vue.config.js
文件来包含
devServer
配置,类似下面这样:
const{ defineConfig }=require('@vue/cli-service');
module.exports =defineConfig({transpileDependencies:true,// 配置开发服务器devServer:{host:'www.bingo.com',// 指定开发服务器监听的域名port:80,// 指定开发服务器的端口},});
请注意,由于80端口是一个标准的HTTP端口,通常需要管理员权限才能让应用监听在80端口上。在Linux或macOS上,你可能需要使用
sudo
来启动应用。在Windows上,可能需要以管理员权限运行命令行工具。
此外,使用80端口有可能和系统上已经运行的其他服务发生冲突,确保80端口没有被其他应用占用。
使用
www.bingo.com
进行项目访问:
最后,因为我们是在本地开发环境配置,所以实际上并不会直接影响到生产环境的域名和端口设置。生产环境的域名和端口设置依赖于你的服务器和DNS配置。
在Vue CLI中,
vue.config.js
是一个可选的配置文件,如果项目的构建和开发过程中需要自定义选项,可以在项目根目录下创建这个文件。
vue.config.js
提供了很多配置项可以帮助你优化和调整开发以及构建的过程。以下是一些常用的配置项:
- publicPath: 类型:
string
,部署应用包时的基本 URL。用法如下:module.exports ={publicPath: process.env.NODE_ENV==='production'?'/production-sub-path/':'/'}
- outputDir: 类型:
string
,构建时生成的生产环境构建文件的目录。默认在项目根目录下生成一个dist
目录。用法如下:module.exports ={outputDir:'dist'}
- assetsDir: 类型:
string
,放置生成的静态资源 (js、css、img、fonts) 的目录。相对于outputDir
。module.exports ={assetsDir:'assets'}
- indexPath: 类型:
string
,指定生成的index.html
的输出路径,相对于outputDir
。module.exports ={indexPath:'index.html'}
- filenameHashing: 类型:
boolean
,默认情况下,生成的静态资源文件名中包含了hash以控制缓存,你可以通过这个选项关闭。module.exports ={filenameHashing:false}
- pages: 类型:
Object
,在多页面应用下构建应用。每个“page”应该有一个对应的 JavaScript 入口文件。module.exports ={pages:{index:{// page 的入口entry:'src/index/main.js',// 模板来源template:'public/index.html',// 在 dist/index.html 的输出filename:'index.html',},// 当使用只有入口的字符串格式时,默认会使用`public/subpage.html`作为模板,如果不存在,则回退到`public/index.html`模板。subpage:'src/subpage/main.js'}}
- lintOnSave: 类型:
boolean
|'warning'
|'default'
|'error'
,是否在开发环境下通过 eslint-loader 在每次保存时 lint 代码。这个值会默认取[process.env.NODE_ENV
] 的值,是生产构建时禁用。module.exports ={lintOnSave: process.env.NODE_ENV!=='production'}
- runtimeCompiler: 类型:
boolean
,是否使用包含运行时编译器的 Vue 构建版本。设置为true
后你就可以在 Vue 组件中使用template
选项了。module.exports ={runtimeCompiler:true}
- transpileDependencies: 类型:
Array<string | RegExp>
,默认情况下 babel-loader 会忽略所有 node_modules 中的文件。如果你想要通过 Babel 显式转译一个依赖,可以在这个选项中列出来。module.exports ={transpileDependencies:[/my-dependency/]}
这些是
vue.config.js
中比较常见和有用的配置项。对于更详细的配置和更高级的用法,建议查看Vue CLI官方文档。
安装axios模块
npm install axios --save --registry https://registry.npmjs.org/
view.HomeView.vue
内容详解:
<template><divclass="home"><imgalt="Vue logo"src="../assets/logo.png"><HelloWorldmsg="Welcome to Your Vue.js App"/></div></template><script>// @ is an alias to /srcimport HelloWorld from'@/components/HelloWorld.vue'exportdefault{name:'HomeView',components:{
HelloWorld
}}</script>
在 Vue 组件中,
name
选项用于指定组件的名称。虽然这个选项不是必须的,但它在某些场景下扮演了重要的角色,提供了以下几个好处:
- 调试:当你在开发工具(如 Vue Devtools)中调试应用时,有名字的组件会更容易识别和跟踪。没有名称的组件可能仅显示为
<AnonymousComponent>
,这使得调试变得更加困难。 - 递归组件:如果一个组件需要在其模板内递归地调用自己,那么为这个组件指定一个
name
是必须的。这样组件就可以通过其名称引用自己,实现递归渲染。 - keep-alive:
<keep-alive>
是 Vue 提供的一个抽象组件,用于保留组件状态或避免重新渲染。在使用<keep-alive>
时,include
和exclude
属性允许你指定哪些组件应该被缓存或忽略。这两个属性接受组件name
作为参数,因此在这种场景下name
选项非常有用。 - Vue 组件库:在创建可复用的组件库时,为每个组件指定一个
name
选项可以更方便地管理和使用这些组件。特别是在全局注册组件的时候,Vue 将使用组件的name
选项作为组件的标识。
示例中的
name: 'App'
表示将这个根组件的名称设为 “App”。这对调试非常有帮助,因为如果出现错误或需要在 Vue Devtools 中查看组件层次结构时,你可以轻松找到名为 “App” 的根组件。
总之,
name
选项虽不是必须的,但在实践中为组件指定名称是一个好习惯,尤其是在以上提到的几种场景中。它有助于提升代码可读性和维护性,并且在开发、调试以及构建可重用组件时,使得工作流程更加顺畅。
**在JavaScript(包括用于开发Vue应用的ES6标准)中,除了
export default
之外,还有
export
关键字用于导出模块的其他成员。
export default
和
export
共同构成了ES6的模块导出机制,它们之间有几个关键的区别:**
export default
- 每个模块可以有一个
default
导出。 - 使用
export default
时,导入时可以为其指定任意名称。 - 主要用于导出模块的“主要”功能或值。
例如,导出一个函数:
exportdefaultfunction(){ console.log("Hello World!");}
导入时:
import myFunction from'./myModule';
export
- 一个模块可以导出多个(非默认)成员。
- 导入时需要使用相同的名称,或者使用
as
关键字重命名。 - 用于导出一个模块的多个功能或值。
例如,导出多个函数或变量:
exportconst myConstant =123;exportfunctionmyFunction(){ console.log("Hello World!");}exportclassMyClass{}
导入时:
import{ myFunction, myConstant, MyClass as RenamedClass }from'./myModule';
**结合使用
export default
和
export
**:
一个模块中可以同时使用
export default
和
export
来导出多个成员,其中一个作为默认导出,而其他则作为具名导出。
// myModule.jsexportdefaultfunction(){ console.log("Default Function");}exportfunctionmyFunction(){ console.log("My Function");}exportconst myConstant =123;
导入时:
// 引入默认导出的函数,可以任意命名import defaultFunction,{ myFunction, myConstant }from'./myModule';
注意事项:
export default
允许你导出模块时不必使用大括号,而export
导出的成员则需要在导入时放在大括号内。- 当使用
export
导出多个成员时,导入这些成员必须使用它们原有的名字,除非使用as
关键字进行重命名。 export default
的主要优势在于简化了默认导出成员的导入语法,因为你不需要使用大括号并且可以自由命名导入的成员。
这种模块化机制极大地增强了JavaScript代码的组织性和可维护性,使开发者可以轻松地在不同的文件和模块之间共享功能和值。
总结 export default与export
export default
: 由于每个模块文件只能有一个默认导出,因此在导入时可以随意命名。这意味着无论在导出时成员被命名为什么,在导入时都可以自定义命名,而 JavaScript 会理解你指的是该文件的默认导出成员。这就是为什么export default
能使导入语法变得简化和灵活。export
: 允许一个模块导出多个成员。由于可能同时导出多个成员,每个成员都有自己的名字,所以在导入这些成员时需要明确指出导入成员的具体名称。这样做是为了保证明确性和一致性,确保在导入时 JavaScript 知道你指的是哪个具体成员。如果需要,在导入时改变名称,可以使用as
关键词来重命名,这样做即可以保持导入成员的明确性,又能提供一定程度的灵活性。
综上所述,这两种导出(
export
和
export default
)方式提供了不同级别的灵活性和明确性,以适应不同的使用场景。选择哪一种方式取决于你的具体需求,例如,当模块只提供一个主要功能或值时,使用
export default
比较方便;而当模块提供多个函数、变量或组件时,使用
export
可以同时导出它们,使得导入这些成员时更加清晰明确。
从 Vue 3.0 开始,
<script setup>
是为了简化组合式 API 的使用而提出的一个编译时语法糖。当使用
<script setup>
时,您不能以传统的方式(
export default {}
)导出组件选项。
<script setup>
标签内部的代码被视为组件的顶层代码,因此直接定义变量、函数以及其他响应式状态即可,无需封装在
export default {}
里。
- 移除
export default
声明。 - 直接在
<script setup>
内部声明组件的逻辑。 - 如果需要定义组件的
name
,可以通过defineComponent
的方式。 将天气预报的代码进行vue-cli的修改 view.ShowCenter.vue
<template><h1class="showcenter">Show Center</h1><inputtype="text"v-model="city"><button@click="getque"class="table-bordered">查询城市天气</button><div>当前查询城市: {{city}}</div><p></p><tablev-if="data1!=''"><tr><th>序号</th><th>城市</th><th>日期</th><th>白天天气</th><th>夜间天气</th><th>最高温度</th><th>最低温度</th><th>相对湿度</th><th>能见度</th></tr><trv-for="(tq,index) in data1"><td>{{index+1}}</td><td>{{city}}</td><td>{{tq.fxDate}}</td><td>{{tq.textDay}}</td><td>{{tq.textNight}}</td><td>{{tq.tempMax}}</td><td>{{tq.tempMin}}</td><td>{{tq.humidity}}</td><td>{{tq.vis}}</td></tr></table></template><scriptsetup>import{ defineComponent, ref, onMounted }from'vue';import axios from"axios";defineComponent({name:'show-center'});// 以 ref 创建响应式变量const data1 =ref([]);const id =ref('');const city =ref('北京');// 定义获取数据的方法constgetque=async()=>{try{const{data: locationData }=await axios.get(`https://geoapi.qweather.com/v2/city/lookup?location=${city.value}&key=dc7728d14dfb4c6eb3eadc070a5839&lang=zh`);
console.log(locationData.location);// 省略业务逻辑
city.value = locationData.location[0].name;
id.value = locationData.location[0].id;
console.log(data1.value, id.value);const{data: weatherData }=await axios.get(`https://devapi.qweather.com/v7/weather/7d?location=${id.value}&key=dc7728d14dfb4c6eb3eadc070a5839&lang=zh`);
console.log(weatherData.daily);
data1.value = weatherData.daily;}catch(error){
console.error("请求时发生错误:", error);}};// 使用 onMounted 生命周期钩子onMounted(()=>{getque();});</script><stylescoped>table,tr,th,td{border: 3px solid red;border-collapse: collapse;}th ,td{width: 200px;text-align: center;height: 30px;line-height: 30px;}.co{background-color: orange;}</style>
在这段代码中,我们通过
defineComponent({ name: 'showcenter' })
来定义组件名称,使用
ref
创建响应式变量来替代原有的
data(){}
定义方式。函数和生命周期钩子直接定义在
<script setup>
的顶级作用域中,这样既符合
<script setup>
的使用规范,又保持了原有逻辑的完整性。
请注意,当使用
<script setup>
时,组件的大部分功能都可以通过直接在脚本中声明来实现,无需包裹在
export default {}
里。另外,如果您的项目中还未启用
<script setup>
,或不打算使用它的特性,建议回归到传统 Vue 组件的写法。
const { data: locationData } = await axios.get(`https://geoapi.qweather.com/v2/city/lookup?location=${city.value}&key=dc7728d14dfb4c6eb3eadc070a5839&lang=zh`);
这行代码使用了几个JavaScript和Vue.js中常见的技术点,包括解构赋值、模板字符串、await关键字以及axios库的使用。下面我会逐一解释这些技术点:
- axios库: axios是一个基于Promise的HTTP客户端,用于浏览器和node.js环境中发送HTTP请求。在这段代码中,
axios.get
方法用于向指定的URL发送GET请求。 - 模板字符串: 使用
反引号
括起来的字符串称为模板字符串,它允许你在字符串中嵌入变量或表达式。${city.value}
这部分代码会被替换为city.value
变量的实际值,变量city
可能是一个响应式变量,通过Vue的ref
或reactive
函数创建。 - await关键字:
await
关键字用于等待一个Promise对象的结果。它只能在异步函数(通过async
定义的函数)中使用。在这里,它用于等待axios.get
发送请求并返回响应的过程完成。 - 解构赋值: 解构赋值允许你将数组或对象的属性/值“解构”到不同的变量中。在这个例子中,
const { data: locationData } = ...
从axios返回的响应对象中解构出data
属性,并将其重命名为locationData
。这意味着你可以直接使用locationData
变量访问原响应对象中data
属性的值。
综上所述,这行代码的执行流程如下:
- 使用
axios.get
向https://geoapi.qweather.com/v2/city/lookup
发送GET请求,请求参数包括location
(其值取自city.value
)、key
(API密钥)和lang
(语言偏好)。 - 请求发送后,
await
会暂停当前异步函数的执行,直到Promise解决并返回响应结果。 - axios的Promise解决后,其返回的响应对象中的
data
属性被解构并赋值给locationData
变量。 - 现在,
locationData
包含了从天气API获得的、关于请求位置的信息,可以在后续代码中使用这些数据。
错误处理:
通过
try-catch
捕捉错误,但由于
Axios
请求使用的是
Promise
(并且被 .then 方法处理),错误不会被
try-catch
捕获到,除非
Axios
请求中使用
await
。
const getque = async () => {}
是一个使用 ES6 箭头函数语法和
async
关键字定义的异步函数。这个函数可以进行异步操作,比如网络请求、读写文件等不会立即完成的操作,并使用
await
关键字以同步的方式写异步代码。这种语法提供了一种更简洁和直观的方式来处理 JavaScript 中的异步编程。下面将分步骤详细介绍这一语法。
constgetque=async()=>{}语法详解
1. 箭头函数 (
() => {}
)
箭头函数是一种在 ES6 (ECMAScript 2015) 中引入的简写形式,用于定义函数。与传统的函数定义方式相比,箭头函数提供了更简洁的语法。
- 基本语法:
(parameters)=>{ statements }
如果函数只有一个参数,可以省略参数周围的括号:
parameter=>{ statements }
如果函数体只有一条语句,且是返回值的话,可以省略大括号和
return
关键字:
parameter=> expression
// 等价于parameter=>{return expression;}
- **没有自己的
this
**:
箭头函数没有自己的
this
值,它会捕获其所在上下文的
this
值为自己的
this
,使得在回调函数中的
this
行为变得更加可预测。
2.
async
关键字
async
是一个在函数定义前使用的关键字,表明该函数是异步的。
async
函数总是返回一个
Promise
对象。如果
async
函数显式返回一个非
Promise
值,这个值会被自动包裹在一个
Promise
中。
asyncfunctionmyFunction(){return'Hello';}myFunction().then(alert);// 弹出 'Hello'
使用箭头函数定义异步函数的形式如下:
constmyAsyncFunction=async()=>{// 异步操作};
3.
await
关键字
在
async
函数内部,可以使用
await
关键字来等待一个
Promise
完成。它会暂停
async
函数的执行,直到
Promise
完成(即
Promise
被 “resolve” 或 “reject”),然后继续执行
async
函数,并返回结果。
- 基本用法:
const data =awaitsomeAsyncOperation();
await
只能在
async
函数内部使用,如果在普通函数中使用
await
,会引发语法错误。
总结
const getque = async () => {}
定义了一个名为
getque
的异步函数,该函数内部可以包含异步操作,如进行网络请求或者执行其他返回
Promise
对象的操作。通过
async
和
await
的组合使用,可以以更接近同步编程的方式写出清晰、简洁的异步代码。
route.index.js
import{ createRouter, createWebHistory }from'vue-router'import HomeView from'../views/HomeView.vue';import showcenter from'../views/ShowCenter.vue'const routes =[{path:'/',name:'showcenter',component: showcenter
},{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/AboutView.vue')}]const router =createRouter({history:createWebHistory(process.env.BASE_URL),
routes
})exportdefault router
实现效果:
最终前端展示(部分):
view.base.vue
<template><a-layout style="min-height: 100vh"><a-layout-sider v-model:collapsed="collapsed" collapsible><div class="logo"
style="font-style: italic;text-align: center;font-size: 20px;color:#fff;margin: 10px 0;line-height: 50px;font-family: 'Times New Roman'"><!--a-switch是指定开关--><span><a-switch v-model:checked="checked"/> DevOps</span></div><a-menu v-for="list in menu_list" v-model:selectedKeys="selectedKeys" theme="dark" mode="inline"><a-menu-item v-if="list.children.length==0" key="list.id"><Myicons :icon="list.icon"></Myicons><!--跳转路由--><span><router-link :to="list.menu_url">{{list.title}}</router-link></span></a-menu-item><a-sub-menu v-else:key="list.id"><template #title><span><!--引用子组件components.myicons.vue--><myicons :icon="list.icon"></myicons><span>{{list.title}}</span></span></template><a-menu-item v-for="children in list.children":key="children.id"><router-link :to="children.menu_url">{{children.title}}</router-link></a-menu-item></a-sub-menu></a-menu></a-layout-sider><a-layout><a-layout-header style="background: #fff; padding: 0"/><a-layout-content style="margin: 0 16px"><a-breadcrumb style="margin: 16px 0"><a-breadcrumb-item>User</a-breadcrumb-item><a-breadcrumb-item>Bill</a-breadcrumb-item></a-breadcrumb><div :style="{ padding: '24px', background: '#fff', minHeight: '785px' }"><router-view/></div></a-layout-content><a-layout-footer style="text-align: center">
Panda Design ©2024 Created by Ant cong
</a-layout-footer></a-layout></a-layout></template><script setup>import Myicons from"@/components/Myicons.vue";import{reactive, ref}from'vue';const collapsed =ref(false);const selectedKeys =ref(['1']);const checked=ref(false);const menu_list =reactive([{id:1,icon:'settings',title:'系统管理',tube:'',menu_url:'/uricgo/show_center',children:[]},{id:2,icon:'desktop',title:'资产管理',menu_url:'/uricgo/host',children:[]},{"id":3,icon:'cloud',title:'批量任务',tube:'',menu_url:'/uricgo/workbench',children:[{id:10,icon:'mail',title:'执行任务',menu_url:'/uricgo/multi_exec'},{id:11,icon:'mail',title:'命令管理',menu_url:'/uricgo/template_manage'},]},{id:4,icon:'git',title:'代码发布',tube:'',menu_url:'/uricgo/workbench',children:[{id:12,title:'应用管理',menu_url:'/uricgo/release'},{id:13,title:'发布申请',menu_url:'/uricgo/release'}]},{id:5,icon:'history',title:'定时计划',tube:'',menu_url:'/uricgo/workbench',children:[]},{id:7,icon:'monitor',title:'监控预警',tube:'',menu_url:'/uricgo/workbench',children:[]},{id:9,icon:'user',title:'用户中心',tube:'',menu_url:'/uricgo/workbench',children:[{id:20,title:'账户管理',tube:'',menu_url:'/uricgo/workbench'},{id:21,title:'角色管理',tube:'',menu_url:'/uricgo/workbench'},{id:22,title:'系统设置',tube:'',menu_url:'/uricgo/workbench'}]}]);</script><style scoped>
#components-layout-demo-side .logo {height: 32px;margin: 16px;background:rgba(255,255,255,0.3);}.site-layout .site-layout-background {background: #fff;}[data-theme='dark'].site-layout .site-layout-background {background: #141414;}</style>
route.index.js
import{ createRouter, createWebHistory }from'vue-router'import showcenter from'../views/ShowCenter.vue'import Time from'../views/ShowCenter-backup.vue'import login from'../views/login.vue'import base from'../views/base.vue'import hosts from'../views/hosts.vue'const routes =[{path:'/bingo',alias:'/',name:'base',component: base,children:[{path:"Time",alias:"",name:"time",component: Time
},{path:"host",name:"host",component:hosts
},{path:'showcenter',name:"showcenter",component:showcenter
},]},{meta:{title:'账户登陆'},path:'/login',name:'Login',component: Login // 快捷键:Alt+Enter快速导包},]const router =createRouter({history:createWebHistory(process.env.BASE_URL),
routes
})exportdefault router
页面展示效果:
版权归原作者 weixin_45782719 所有, 如有侵权,请联系我们删除。