前端基础-05VUE基础02
01 组件化思维
生产环境一般不会直接导入一个js文件,通过组件
网页中实现一个功能,需要使用html定义功能的内容结构,使用css声明功能的外观样式,还要使用js来定义功能的特效
把一个功能相关的[HTML、css和javascript]代码封装在一起组成一个整体的代码块封装模式,我们称之为“组件”
默认组件-示例
组件名 button-counter 可以随意
Data 数据
Template 模板 存放html内容的属性
不支持css
不支持 CSS (No CSS support) 意味着当 HTML 和 JavaScript 组件化时,CSS 明显被遗漏
数据隔离
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="vue3.js"></script>
</head>
<body>
<div id="components-demo">
<button-counter></button-counter>
<button-counter></button-counter>
<button-counter/>
</div>
<script>
// 创建一个Vue应用
const app=Vue.createApp({});
// 定义一个名为button-counter的新全局组件
app.component('button-counter',{
data(){
return{
count:0
}
},
template:`
<button @click="count++">
You clicked me {{count}} times.
</button>`,
style:{
color:"red",
}
});
app.mount('#components-demo')
</script>
</body>
</html>
单文件组件
Vue 单文件组件(又名 *.vue 文件,缩写为 SFC)是一种特殊的文件格式,它允许将 Vue 组件的模板、逻辑 与 样式封装在单个文件中。
<template>
<p class="greeting">{{ greeting }}</p>
</template>
<script>
export default {
data() {
return {
greeting: 'Hello World!'
}
}
}
</script>
<style scoped>
.greeting {
color: red;
font-weight: bold;
}
</style>
Script存放数据
Template存放html代码
Style存放css代码
虽然 SFC 需要一个构建步骤,但益处颇多:
使用熟悉的 HTML、CSS 与 JavaScript 语法编写模块化组件
预编译模板
组件作用域 CSS
通过交叉分析模板与脚本进行更多编译时优化
IDE 支持 模板表达式的自动补全与类型检查
开箱即用的热模块更换(HMR)支持
02脚手架 vue/cli
Vue/cli
Vite
安装vue/cli
关于旧版本: Vue CLI 的包名称由 vue-cli 改成了 @vue/cli。 如果你已经全局安装了旧版本的 vue-cli (1.x 或 2.x),你需要先通过 npm uninstall vue-cli -g 或 yarn global remove vue-cli 卸载它。
Vue CLI 4.x 需要 Node.js v8.9 或更高版本 (推荐 v10 以上)。
Js作为前端语言使用。不仅能做前端
Node.js 相当于python的解释器 python.exe
Pip包 安装第三方依赖包,nodejs中有npm相当于pip
后端可选择
Javascript
Java
Go
Python等
Vue-cli支持后端
Express相当于nodejs javascript框架
1 下载node vue一定要在4.5以上
1 下载nodejs
http://nodejs.cn/download/
2 安装vue/cli
C:\Users\zhu>npm install -g @vue/cli
3 更新
C:\Users\zhu>npm update -g @vue/cli
03 使用
创建项目hello-world
1 创建vue create hello-world
D:\GoWork\src\gitee.com\zhutao2014\s9\day13>vue create hello-world
2选择安装组件
Babel勾选上
Router勾选上
Linter会严格检查语法,取消掉
回车
3选择3.x版本
4 选择历史模式路由
5 选择配置方式package.json
6 保存预处理记录
可以取名字为 basePro,相当于保存了一个配置模板。
想要删除,可以找到window用户家目录下.vuerc,删除"presets": {} 中{}内的内容。
2 创建成功后,启动
3执行完成后
4 访问最终页面
这个是给配置起名字
04
npm是nodejs配套命令
单页面开发 spa: single page application
代码都写好后,不用vue-cli
通过webpack打包
生成静态文件。
把静态文件放到nginx
目录结构
文件说明
src
package-lock 锁相关的
package.json
安装包,依赖于哪个环境
package.json 记录信息
package.json和node_model的关系
hello-world\package.json
内部提供的脚本环境
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build"
},
依赖
"dependencies": {
"core-js": "^3.8.3",
"vue": "^3.2.13",
"vue-router": "^4.0.3"
},
"devDependencies": {
"@vue/cli-plugin-babel": "~5.0.0",
"@vue/cli-plugin-router": "~5.0.0",
"@vue/cli-service": "~5.0.0"
},
包存放的位置 node_modules
安装axios
给hello-world项目安装axios
从node_modules中引入axios
D:\GoWork\src\gitee.com\zhutao2014\s9\day13\vue-test\hello-world>npm install axios
1 hello-world\public\index.html
D:\GoWork\src\gitee.com\zhutao2014\s9\day13\hello-world\public\index.html
<div id="app"></div>
2 hello-world\src\main.js
D:\GoWork\src\gitee.com\zhutao2014\s9\day13\hello-world\src\main.js
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
createApp(App).use(router).mount('#app')
mount加载#app的区域
3 hello-world\src\App.vue
D:\GoWork\src\gitee.com\zhutao2014\s9\day13\hello-world\src\App.vue
router-link 带触发事件的标签,类似于a标签
router-view用于展示的标签
<template>
<nav>
<router-link to="/">Home</router-link> |
<router-link to="/about">About</router-link>
</nav>
<router-view/>
</template>
单文件组件模式流程
Main.js往index.html填充
App.vue 单文件组件
App.vue
修改后保存,自动重启
<template>
<!-- <nav>-->
<!-- <router-link to="/">Home</router-link> |-->
<!-- <router-link to="/about">About</router-link>-->
<!-- </nav>-->
<!-- <router-view/>-->
<h1>Welcome to VUE</h1>
</template>
单文件组件-导入组件三部曲
修改App.vue
D:\GoWork\src\gitee.com\zhutao2014\s9\day13\hello-world\src\App.vue
1 导入子组件 import
@ 符号相当于src路径
2 暴露组件export components
注意 export default 对应的name: 'App',为文件名App.vue
3 使用子组件<HelloWorld>
<template>
<!-- <nav>-->
<!-- <router-link to="/">Home</router-link> |-->
<!-- <router-link to="/about">About</router-link>-->
<!-- </nav>-->
<!-- <router-view/>-->
<h1>Welcome to VUE</h1>
<HelloWorld></HelloWorld>
</template>
<script>
// @ is an alias to /src
import HelloWorld from '@/components/HelloWorld.vue'
export default {
name: 'App',
components: {
HelloWorld
}
}
</script>
打印结果
示例
App.vue嵌套Home.vue
<template>
<h1>Welcome to VUE</h1>
<Home></Home>
</template>
<script>
// @ is an alias to /src
import HelloWorld from '@/components/HelloWorld.vue'
import Home from '@/views/Home.vue'
export default {
name: 'App',
components: {
HelloWorld,
Home
}
}
</script>
Home.vue嵌套 HelloWorld.vue
<template>
<div class="home">
<img alt="Vue logo" src="../assets/logo.png">
<HelloWorld/>
</div>
</template>
<script>
import HelloWorld from '@/components/HelloWorld.vue'
export default {
name: "Home",
components:{
HelloWorld
}
}
</script>
<style scoped>
</style>
查看HomeWorld.vue组件
<template>
<h3>hello world</h3>
</template>
<script>
export default {
name: 'HelloWorld',
props: {
msg: String
}
}
</script>
<style scoped>
h3 {
color: red;
}
</style>
App嵌套Home, home嵌套 HelloWorld
vue单文件组件模式本质
1个index.html vue在里面用了不同的js 让页面产生变化
下午05
大组件放views
小组件放在components
创建vue-pro项目
D:\GoWork\src\gitee.com\zhutao2014\s9\day13>vue create vue-pro
router-link具有具体事件的a标签
D:\GoWork\src\gitee.com\zhutao2014\s9\day13\vue-pro\src\App.vue
<template>
<nav>
<router-link to="/">Home</router-link> |
<router-link to="/about">About</router-link>
</nav>
<router-view/>
</template>
router目录里的js文件
D:\GoWork\src\gitee.com\zhutao2014\s9\day13\vue-pro\src\router\index.js
const routes = [
{
path: '/',
name: 'home',
component: HomeView
},
{
path: '/about',
name: 'about',
component: () => import(/* webpackChunkName: "about" */ '../views/AboutView.vue')
}
]
无论访问哪个路径,都是访问的index.html页面
D:\GoWork\src\gitee.com\zhutao2014\s9\day13\vue-pro\src\App.vue
<template>
<h1>hello user</h1>
</template>
router-view 标签
router-view根据不同的路由关系,找到组件
插入到app.vue的router-view的位置
route-link组件
D:\GoWork\src\gitee.com\zhutao2014\s9\day13\vue-pro\src\App.vue
<template>
<nav>
<router-link to="/">Home</router-link> |
<router-link to="/about">About</router-link>
</nav>
<router-view/>
</template>
点击route-link 切换到route-view对应的组件
dom替换
route-link和a标签区别
router-link是js的dom的替换
a标签是一次http的get请求
练习加路由
App.vue添加
<router-link to="/test1">test1</router-link>
修改路由 添加
hello-world\src\router\index.js
import Test1 from '../views/Test1.vue'
{
path: '/test1',
name: 'test1',
component: Test1
}
下午06
构建Nav组件
<template>
<div>
<ul>
<li v-for="menu in menu_list"><a :href="menu.link">{{ menu.name }}</a></li>
<li>
<span>所在地:</span><select v-model="city" name="" id="">
<option value="北京">北京</option>
<option value="上海">上海</option>
<option value="深圳">深圳</option>
</select>
</li>
</ul>
</div>
</template>
<script>
export default {
name: "Nav",
data() {
return {
menu_list: [
{name: "百度", "link": "http://www.baidu.com"},
{name: "腾讯", "link": "http://www.qq.com"},
{name: "小米", "link": "http://www.xiaomi.com"},
],
city: "北京",
}
},
}
</script>
<style scoped>
ul, li {
list-style: none;
padding: 0;
margin: 0;
}
ul::after {
overflow: hidden;
clear: both;
display: block;
content: "";
}
li {
float: left;
margin: 0 20px;
}
a {
text-decoration: none;
color: #666;
}
</style>
下拉菜单
<li>
<span>所在地:</span><select v-model="city" name="" id="">
<option value="北京">北京</option>
<option value="上海">上海</option>
<option value="深圳">深圳</option>
</select>
</li>
构建home.vue组件
三部曲:在home.vue中添加Nva组件
①引入Import ②暴露组件export ③使用Nav标签
<template>
<div class="home">
<Nav/>
</div>
</template>
<script>
// @ is an alias to /src
import Nav from '@/components/Nav.vue'
export default {
name: 'Home',
components: {
Nav
}
}
</script>
浏览器访问
构建Forecast.vue组件
D:\GoWork\src\gitee.com\zhutao2014\s9\day13\vue-pro\src\components\Forecast.vue
<template>
<h1>天气预报</h1>
</template>
<script>
export default {
name: "Forecast"
}
</script>
<style scoped>
</style>
在再home中引入天气预报组件
<template>
<div class="home">
<Nav/>
<Forecast/>
</div>
</template>
<script>
// @ is an alias to /src
import Nav from '@/components/Nav.vue'
import Forecast from "@/components/Forecast";
export default {
name: 'Home',
components: {
Forecast,
Nav
}
}
</script>
修改Forecast.vue组件
找到内容,放到页面
<template>
<h1>天气预报</h1>
<p><input type="text" placeholder="请输入查询城市" v-model="city">
<button @click="sendAjax">查询</button>
</p>
<table border="1" v-if="forecasts.length>1">
<tr>
<td>日期</td>
<td>天气</td>
<td>最高气温</td>
<td>最低气温</td>
<td>风向</td>
</tr>
<tr v-for="day_forecast in forecasts">
<td>{{day_forecast.date}}</td>
<td>{{day_forecast.type}}</td>
<td>{{day_forecast.high}}</td>
<td>{{day_forecast.low}}</td>
<td>{{day_forecast.fengxiang}}</td>
</tr>
</table>
</template>
放js代码
<script>
export default {
name: "Forecast",
data() {
return {
forecasts:[],
city:"北京"
}
},
methods: {
sendAjax() {
var that=this
// alert(123)
axios.get("http://wthrcdn.etouch.cn/weather_mini",{
params:{
// city:"北京"
city:this.city
}
}).then(function (response){
console.log("response",response)
that.forecasts=response.data.data.forecast
})
},
},
created(){
this.sendAjax()
}
}
</script>
样式拿过来
<style scoped>
tr td{
padding: 10px;
width:80px;
}
</style>
此时没有axios
安装
D:\GoWork\src\gitee.com\zhutao2014\s9\day13\vue-pro>npm install axios
1 记录模块名 版本号
D:\GoWork\src\gitee.com\zhutao2014\s9\day13\vue-pro\package.json
"dependencies": {
"axios": "^0.26.1",
"core-js": "^3.8.3",
"vue": "^3.2.13",
"vue-router": "^4.0.3"
},
2 node_models中下载下来
D:\GoWork\src\gitee.com\zhutao2014\s9\day13\vue-pro\node_modules\axios
导入包
D:\GoWork\src\gitee.com\zhutao2014\s9\day13\vue-pro\src\components\Forecast.vue
<script>
import axios from "axios"; //要导入的包直接写包名即可,不需要使用路径
export default {
name: "Forecast",
data() {
return {
forecasts:[],
city:"北京"
}
},
打印结果
调整表格居中
添加margin: 0 auto;
D:\GoWork\src\gitee.com\zhutao2014\s9\day13\vue-pro\src\components\Forecast.vue
<style scoped>
table {
margin: 0 auto;
}
tr td{
padding: 10px;
width:100px;
}
</style>
文本居中
App.vue中默认有文本居中
D:\GoWork\src\gitee.com\zhutao2014\s9\day13\vue-pro\src\App.vue
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
}
打印结果
export default 是 js的导出格式
created 点击按钮前加载
<script>
import axios from "axios"; //要导入的包直接写包名即可,不需要使用路径
export default {
name: "Forecast",
data() {
return {
forecasts:[],
city:"北京"
}
},
methods: {
sendAjax() {
var that=this
// alert(123)
axios.get("http://wthrcdn.etouch.cn/weather_mini",{
params:{
// city:"北京"
city:this.city
}
}).then(function (response){
console.log("response",response)
that.forecasts=response.data.data.forecast
})
},
},
created(){
this.sendAjax()
}
}
</script>
综合练习
完整代码
Nav.vue
D:\GoWork\src\gitee.com\zhutao2014\s9\day13\vue-pro\src\components\Nav.vue
<template>
<div>
<ul>
<li v-for="menu in menu_list"><a :href="menu.link">{{ menu.name }}</a></li>
<li>
<span>所在地:</span><select v-model="city" name="" id="">
<option value="北京">北京</option>
<option value="上海">上海</option>
<option value="深圳">深圳</option>
</select>
</li>
</ul>
</div>
</template>
<script>
export default {
name: "Nav",
data() {
return {
menu_list: [
{name: "百度", "link": "http://www.baidu.com"},
{name: "腾讯", "link": "http://www.qq.com"},
{name: "小米", "link": "http://www.xiaomi.com"},
],
city: "北京",
}
},
}
</script>
<style scoped>
ul, li {
list-style: none;
padding: 0;
margin: 0;
}
ul::after {
overflow: hidden;
clear: both;
display: block;
content: "";
}
li {
float: left;
margin: 0 20px;
}
a {
text-decoration: none;
color: #666;
}
</style>
Forecast.vue
D:\GoWork\src\gitee.com\zhutao2014\s9\day13\vue-pro\src\components\Forecast.vue
<template>
<h1>天气预报</h1>
<p><input type="text" placeholder="请输入查询城市" v-model="city">
<button @click="sendAjax">查询</button>
</p>
<table border="1" v-if="forecasts.length>1">
<tr>
<td>日期</td>
<td>天气</td>
<td>最高气温</td>
<td>最低气温</td>
<td>风向</td>
</tr>
<tr v-for="day_forecast in forecasts">
<td>{{day_forecast.date}}</td>
<td>{{day_forecast.type}}</td>
<td>{{day_forecast.high}}</td>
<td>{{day_forecast.low}}</td>
<td>{{day_forecast.fengxiang}}</td>
</tr>
</table>
</template>
<script>
import axios from "axios"; //要导入的包直接写包名即可,不需要使用路径
export default {
name: "Forecast",
data() {
return {
forecasts:[],
city:"北京"
}
},
methods: {
sendAjax() {
var that=this
// alert(123)
axios.get("http://wthrcdn.etouch.cn/weather_mini",{
params:{
// city:"北京"
city:this.city
}
}).then(function (response){
console.log("response",response)
that.forecasts=response.data.data.forecast
})
},
},
created(){
this.sendAjax()
}
}
</script>
<style scoped>
table {
margin: 0 auto;
}
tr td{
padding: 10px;
width:100px;
}
</style>
Home.vue
D:\GoWork\src\gitee.com\zhutao2014\s9\day13\vue-pro\src\views\Home.vue
<template>
<div class="home">
<Nav/>
<Forecast/>
</div>
</template>
<script>
// @ is an alias to /src
import Nav from '@/components/Nav.vue'
import Forecast from "@/components/Forecast";
export default {
name: 'Home',
components: {
Forecast,
Nav
}
}
</script>
Index.js
D:\GoWork\src\gitee.com\zhutao2014\s9\day13\vue-pro\src\router\index.js
import { createRouter, createWebHistory } from 'vue-router'
import Home from '../views/Home.vue'
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/AboutView.vue')
}
]
const router = createRouter({
history: createWebHistory(process.env.BASE_URL),
routes
})
export default router
App.vue
D:\GoWork\src\gitee.com\zhutao2014\s9\day13\vue-pro\src\App.vue
<template>
<!-- <nav>-->
<!-- <router-link to="/">Home</router-link> |-->
<!-- <router-link to="/about">About</router-link> -->
<!-- </nav> -->
<router-view/>
</template>
<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>
下午07 子给父
组件和组件之间传递数据
Nav.vue的值传给Home.vue
D:\GoWork\src\gitee.com\zhutao2014\s9\day13\vue-pro\src\views\Home.vue
<template>
<div class="home">
<Nav/>
<p>选中的城市:{{city}}</p>
<Forecast/>
</div>
</template>
显示选中的城市
子组件传递 事件给父组件
在子组件中,通过this.$emit('自定义事件名', 参数1,参数2,...)来调用父组件中定义的事件.
Nav.vue是子组件
Home.vue父组件配置
D:\GoWork\src\gitee.com\zhutao2014\s9\day13\vue-pro\src\views\Home.vue
1 添加data数据city和p标签
2添加methods中collBack函数
3 Nav标签中添加调用,getCity事件调用collBack函数
注意:getCity在子组件在Nav.vue中定义。
<template>
<div class="home">
<Nav @getCity="collBack"></Nav>
<p>选中的城市:{{city}}</p>
<Forecast/>
</div>
</template>
<script>
// @ is an alias to /src
import Nav from '@/components/Nav.vue'
import Forecast from "@/components/Forecast";
export default {
name: 'Home',
data(){
return {
city:""
}
},
components: {
Forecast,
Nav
},
methods:{
collBack(choose_city){
// alert(123)
this.city=choose_city
}
}
}
</script>
Nav.vue子组件配置
D:\GoWork\src\gitee.com\zhutao2014\s9\day13\vue-pro\src\components\Nav.vue
父组件的getCity 是子组件本身的this.city
<template>
<div>
<ul>
<li v-for="menu in menu_list"><a :href="menu.link">{{ menu.name }}</a></li>
<li>
<span>所在地:</span><select v-model="city" name="" id="">
<option value="北京">北京</option>
<option value="上海">上海</option>
<option value="深圳">深圳</option>
</select>
</li>
</ul>
</div>
</template>
<script>
export default {
name: "Nav",
data() {
return {
menu_list: [
{name: "百度", "link": "http://www.baidu.com"},
{name: "腾讯", "link": "http://www.qq.com"},
{name: "小米", "link": "http://www.xiaomi.com"},
],
city: "北京",
}
},
created() {
this.$emit("getCity",this.city);
}
}
</script>
<style scoped>
ul, li {
list-style: none;
padding: 0;
margin: 0;
}
ul::after {
overflow: hidden;
clear: both;
display: block;
content: "";
}
li {
float: left;
margin: 0 20px;
}
a {
text-decoration: none;
color: #666;
}
</style>
排错测试是否调用
methods:{
collBack(choose_city){
// alert(123)
this.city=choose_city
}
}
添加watch
当调整不同内容,created已经不再执行了
D:\GoWork\src\gitee.com\zhutao2014\s9\day13\vue-pro\src\components\Nav.vue
<script>
export default {
name: "Nav",
data() {
return {
menu_list: [
{name: "百度", "link": "http://www.baidu.com"},
{name: "腾讯", "link": "http://www.qq.com"},
{name: "小米", "link": "http://www.xiaomi.com"},
],
city: "北京",
}
},
created() {
this.$emit("getCity",this.city);
},
watch:{
city(newVal,oldVal){
console.log(newVal,oldVal);
this.$emit("getCity",this.city);
}
}
}
</script>
利用watch做同步
下午08 12 父给子传数据
父组件中取值
子组件接收 props
联动
用watch或者updated
修改 不要重复声明
下午13 路由
组件嵌套
设定路由
路由传参 无视频
1 路径参数传参
2 get参数传参
想查询2012/12参数对应的文章
把值传给子组件
下午14
希望能过滤文章
正常拿到年月发送给后端ajax请求
给data赋值
不写死,给数据渲染
作为get请求的参数
最后打包命令
作业 当前全国疫情信息