Vue学习笔记
以下内容为黑马Springboot+Vue3中的Vue3教程部分
Vue概述
什么是Vue?
Vue 是一款用于构建用户界面的渐进式的JavaScript框架。(官方:https://cn.vuejs.org/)
快速入门
-
准备
- 准备html页面,并引入Vue模块(官方提供)
- 创建Vue程序的应用实例
- 准备元素(div),被Vue控制
-
构建用户界面
- 准备数据
- 通过插值表达式渲染页面
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head>
<body><div id="app"><h1>{{msg}}</h1></div><!-- 引入Vue模块 --><script type="module">import {createApp} from 'https://unpkg.com/vue@3/dist/vue.esm-browser.js'/* 创建vue的应用实例 */createApp({data() {return {//定义数据msg: "hello vue3"}}}).mount("#app")</script>
</body>
</html>
Vue常用指令
-
指令:HTML标签上带有 v-前缀的特殊属性,不同的指令具有不同的含义,可以实现不同的功能。
-
常用指令:
v-for
- 作用:列表渲染,遍历容器的元素或者对象的属性
- 语法:
v-for = "(item, index) in items"
- 参数说明:
- items 为遍历的数组
- item 为遍历出来的元素
- index 为索引/下标,从0开始;可以省略,省略index语法:
v-for = "item in items"
- 参数说明:
⭐️注意:遍历的数组,必须在data中定义;要想让哪个标签循环展示多次,就在哪个标签上使用v-for指令。
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><title>Document</title>
</head>
<body><div id="app"><table border="1 solid" colspa="0" cellspacing="0"><tr><th>文章标题</th><th>分类</th><th>发表时间</th><th>状态</th><th>操作</th></tr><!-- 将来哪个元素要出现多次,v-for指令就添加到哪个元素上 --><tr v-for="(article, index) in articleList"><td>{{article.title}}</td><td>{{article.category}}</td><td>{{article.time}}</td><td>{{article.state}}</td><td><button>编辑</button><button>删除</button></td></tr></table></div><script type="module">//导入vue模块import { createApp } from "https://unpkg.com/vue@3/dist/vue.esm-browser.js";//创建应用实例createApp({data() {return {//定义数据articleList: [{title: "医疗反腐绝非砍医护收入",category: "时事",time: "2023-09-5",state: "已发布",},{title: "中国男篮缘何一败涂地?",category: "篮球",time: "2023-09-5",state: "草稿",},{title: "华山景区已受大风影响阵风达7-8级,未来24小时将持续",category: "旅游",time: "2023-09-5",state: "已发布",},],};},}).mount("#app"); //控制页面元素</script>
</body>
</html>
v-bind
- 作用:动态为HTMl标签绑定属性值,如设置href、src、style样式等。
- 语法:
v-bind:属性名="属性值"
- 简化:
:属性名="属性值"
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head>
<body><div id="app"><!-- <a v-bind:href="url">黑马官网</a> --><a :href="url">黑马官网</a></div><script type="module">//引入vue模块import { createApp} from 'https://unpkg.com/vue@3/dist/vue.esm-browser.js'//创建vue应用实例createApp({data() {return {url: 'https://www.itheima.com'}}}).mount("#app")//控制html元素</script>
</body>
</html>
v-if & v-show
- 作用:这两类指令,都是用来控制元素的显示与隐藏的。
-
v-if
- 语法:
v-if="表达式"
,表达式值为 true,显示;false,隐藏。 - 其他:可以配合
v-else-if
/v-else
进行链式调用条件判断。 - 原理:基于条件判断,来控制创建或者移除元素节点(条件渲染)。
- 场景:要么显示,要么不显示,不频繁切换的场景。
- 语法:
-
v-show
- 语法:
v-show="表达式"
,表达式值为 true,显示;false,隐藏。 - 原理:基于CSS样式display来控制显示与隐藏。
- 场景:频繁切换显示隐藏的场景。
- 语法:
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head><body><div id="app">手链价格为: <span v-if="customer.level >= 0 && customer.level <= 1">9.9</span><span v-else-if="customer.level >= 2 && customer.level <= 4">19.9</span> <span v-else>29.9</span><br>手链价格为: <span v-show="customer.level >= 0 && customer.level <= 1">9.9</span><span v-show="customer.level >= 2 && customer.level <= 4">19.9</span> <span v-show="customer.level >= 5">29.9</span></div><script type="module">//导入vue模块import { createApp} from 'https://unpkg.com/vue@3/dist/vue.esm-browser.js'//创建vue应用实例createApp({data() {return {customer:{name:'张三',level:6}}}}).mount("#app")//控制html元素</script>
</body></html>
v-on
- 作用:为html标签绑定事件
-
语法:
v-on:事件名="函数名"
- 简写为
@事件名="函数名"
createApp({ data(){需要用到的数据}, methods:{需要用到的方法} })
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head>
<body><div id="app"><button v-on:click="money">点我有惊喜</button> <button @click="love">再点更惊喜</button></div><script type="module">//导入vue模块import { createApp} from 'https://unpkg.com/vue@3/dist/vue.esm-browser.js'//创建vue应用实例createApp({data() {return {//定义数据}},methods: {money: function(){window.alert("送你一百万!")},love: function(){window.alert("爱你一万年!")}}}).mount("#app");//控制html元素</script>
</body>
</html>
v-model
- 作用:在表单元素上使用,双向数据绑定。可以方便的 获取 或 设置 表单项数据
- 语法:
v-model="变量名"
数据和视图会同时发生变化
**注意:**v-model中绑定的变量,必须在data中定义。
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head><body><div id="app">文章分类: <input type="text" v-model="searchConditions.category"/> <span>{{searchConditions.category}}</span>发布状态: <input type="text" v-model="searchConditions.state"/> <span>{{searchConditions.state}}</span><button>搜索</button><button v-on:click="clear">重置</button><br /><br /><table border="1 solid" colspa="0" cellspacing="0"><tr><th>文章标题</th><th>分类</th><th>发表时间</th><th>状态</th><th>操作</th></tr><tr v-for="(article,index) in articleList"><td>{{article.title}}</td><td>{{article.category}}</td><td>{{article.time}}</td><td>{{article.state}}</td><td><button>编辑</button><button>删除</button></td></tr></table></div><script type="module">//导入vue模块import { createApp } from 'https://unpkg.com/vue@3/dist/vue.esm-browser.js'//创建vue应用实例createApp({data() {return {//定义数据searchConditions:{category:'',state:''},articleList: [{title: "医疗反腐绝非砍医护收入",category: "时事",time: "2023-09-5",state: "已发布"},{title: "中国男篮缘何一败涂地?",category: "篮球",time: "2023-09-5",state: "草稿"},{title: "华山景区已受大风影响阵风达7-8级,未来24小时将持续",category: "旅游",time: "2023-09-5",state: "已发布"}]}},methods: {clear: function(){//清空category以及state数据//在method对应的方法里面,使用this就代表的是vue实例,可以使用this获取到vue实例中准备的数据this.searchConditions.category='';this.searchConditions.state='';}},}).mount("#app")//控制html元素</script>
</body></html>
vue生命周期
- 生命周期:指一个对象从创建到销毁的整个过程
- 生命周期的八个阶段:每个阶段会自动执行一个生命周期方法(钩子函数),让开发者有机会在特定的阶段执行自己的代码
应用场景:
- 在页面加载完毕时,发起异步请求,加载数据,渲染页面。
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head><body><div id="app">文章分类: <input type="text" v-model="searchConditions.category"/> <span>{{searchConditions.category}}</span>发布状态: <input type="text" v-model="searchConditions.state"/> <span>{{searchConditions.state}}</span><button>搜索</button><button v-on:click="clear">重置</button><br /><br /><table border="1 solid" colspa="0" cellspacing="0"><tr><th>文章标题</th><th>分类</th><th>发表时间</th><th>状态</th><th>操作</th></tr><tr v-for="(article,index) in articleList"><td>{{article.title}}</td><td>{{article.category}}</td><td>{{article.time}}</td><td>{{article.state}}</td><td><button>编辑</button><button>删除</button></td></tr></table></div><script type="module">//导入vue模块import { createApp } from 'https://unpkg.com/vue@3/dist/vue.esm-browser.js'//创建vue应用实例createApp({data() {return {//定义数据searchConditions:{category:'',state:''},articleList: [{title: "医疗反腐绝非砍医护收入",category: "时事",time: "2023-09-5",state: "已发布"},{title: "中国男篮缘何一败涂地?",category: "篮球",time: "2023-09-5",state: "草稿"},{title: "华山景区已受大风影响阵风达7-8级,未来24小时将持续",category: "旅游",time: "2023-09-5",state: "已发布"}]}},methods: {clear: function(){//清空category以及state数据//在method对应的方法里面,使用this就代表的是vue实例,可以使用this获取到vue实例中准备的数据this.searchConditions.category='';this.searchConditions.state='';}},mounted() {console.log('Vue挂载完毕,发送请求获取数据...')},}).mount("#app")//控制html元素</script>
</body></html>
Axios
- 介绍:Axios 对原生的Ajax进行了封装,简化书写,快速开发。
- 官网:https://www.axios-http.cn/
Axios使用步骤
-
引入Axios的js文件(参照官网)
-
使用Axios发送请求,并获取相应结果
method:请求方式,GET/POST…
url:请求路径(必须指定)
data:请求数据
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head>
<body><!-- 引入axios的js文件 --><script src="https://unpkg.com/axios/dist/axios.min.js"></script><script>/* 发送请求 *//* axios({method:'get',url:'http://localhost:8080/article/getAll'}).then(result => {//成功的回调//result代表服务器响应的所有的数据,包含了响应头、响应体,result.data 代表的是接口响应的核心数据console.log(result.data);}).catch(err => {//失败的回调console.log(err);}) */let article={title:'明天会更好',category:'生活',time:'2000-01-01',status:'草稿'}axios({method:'post',url:'http://localhost:8080/article/add',data:article}).then(result => {//成功的回调//result代表服务器响应的所有的数据,包含了响应头、响应体,result.data 代表的是接口响应的核心数据console.log(result.data);}).catch(err => {//失败的回调console.log(err);})</script>
</body>
</html>
Axios-请求方式别名(推荐)
-
为了方便起见,Axios已经为所有支持的请求方法提供了别名
-
格式:
axios.请求方式(url [, data [, config]])
-
GET:
axios.get(url).then(res => {...}).catch(err => {});
-
POST:
axios.post(url, data).then(res => {...}).catch(err => {});
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head>
<body><!-- 引入axios的js文件 --><script src="https://unpkg.com/axios/dist/axios.min.js"></script><script>/* 发送请求 *//* axios({method:'get',url:'http://localhost:8080/article/getAll'}).then(result => {//成功的回调//result代表服务器响应的所有的数据,包含了响应头、响应体,result.data 代表的是接口响应的核心数据console.log(result.data);}).catch(err => {//失败的回调console.log(err);}) */let article={title:'明天会更好',category:'生活',time:'2000-01-01',status:'草稿'}/* axios({method:'post',url:'http://localhost:8080/article/add',data:article}).then(result => {//成功的回调//result代表服务器响应的所有的数据,包含了响应头、响应体,result.data 代表的是接口响应的核心数据console.log(result.data);}).catch(err => {//失败的回调console.log(err);}) *///别名的方式发送请求/* axios.get("http://localhost:8080/article/getAll").then(result => {console.log(result.data); }).catch(err => {console.log(err);}); */axios.post('http://localhost:8080/article/add', article).then(res => {console.log(res.data);}).catch(err => {console.log(err);});</script>
</body>
</html>
案例
使用表格展示所有文章的数据,并完成条件搜索功能
- 钩子函数mounted中,获取所有的文章数据
- 使用v-for指令,把数据渲染到表格上展示
- 使用v-model指令完成表单数据的双向绑定
- 使用v-on指令为搜索按钮绑定单击事件
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head>
<body><div id="app">文章分类: <input type="text" v-model="searchConditions.category">发布状态: <input type="text" v-model="searchConditions.state"><button v-on:click="search">搜索</button><br /><br /><table border="1 solid" colspa="0" cellspacing="0"><tr><th>文章标题</th><th>分类</th><th>发表时间</th><th>状态</th><th>操作</th></tr><tr v-for="(article, index) in articleList"><td>{{article.title}}</td><td>{{article.category}}</td><td>{{article.time}}</td><td>{{state}}</td><td><button>编辑</button><button>删除</button></td></tr></table></div><!-- 导入axios的js文件 --><script src="https://unpkg.com/axios/dist/axios.min.js"></script><script type="module">//导入vue模块import { createApp } from 'https://unpkg.com/vue@3/dist/vue.esm-browser.js';//创建Vue应用实例createApp({data(){return {articleList:[],searchConditions:{category:'',state:''}}},methods: {search:function(){//发送请求,完成搜索,携带搜索条件axios.get('http://localhost:8080/article/search?category=' + this.searchConditions.category + '&state=' + this.searchConditions.state).then(res => {//把得到的数据赋值给articleListthis.articleList = res.data;}).catch(err => {console.log(err);});}},//钩子函数mounted中获取所有文章数据mounted:function(){//发送异步请求 axiosaxios.get('http://localhost:8080/article/getAll').then(res => {//console.log(res.data)this.articleList = res.data;}).catch(err => {console.log(err);});}}).mount('#app');//控制html元素</script>
</body>
</html>
整站使用Vue(工程化)
环境准备
-
介绍:create-vue是Vue官方提供的最新的脚手架工具,用于快速生成一个工程化的Vue项目
-
create-vue提供了如下功能:
- 统一的目录结构
- 本地调试
- 热部署
- 单元测试
- 集成打包
-
依赖环境:NodeJS
-
安装NodeJS
环境准备
- npm:Node Package Manager,是NodeJS的软件包管理器。
Vue项目创建和启动
Vue项目-创建
- 创建一个工程化的Vue项目,执行命令:
npm init vue@latest
,执行上述命令,将会安装并执行 create-vue,它是Vue官方的项目脚手架工具。
Vue项目-安装依赖
-
进入项目目录,执行命令安装当前项目的依赖:
npm intsall
创建项目及安装依赖的过程,都是需要联网的。
Vue项目-目录结构
Vue项目-启动
- 命令行执行命令:
npm run dev
,就可以启动vue项目了。
-
VScode可视化启动项目:
若爆红,查询这篇博客:http://t.csdnimg.cn/3pJ8n
-
访问项目:打开浏览器,在浏览器地址栏访问http://127.0.0.1:5173/就可以访问到vue项目了
Vue项目开发流程
<!-- <script>//写数据export default{data(){return {msg:'上海'}}}
</script> --><script setup>import {ref} from 'vue';//调用ref函数,定义响应式数据const msg = ref('西安')
</script><template><!-- html --><!-- <h1>北京</h1> --><h1>{{ msg }}</h1>
</template><style scoped>/* 样式 */h1{color:red;}
</style>
API风格
- Vue的组件有两种不同的风格:组合式API(推荐)和选项式API
选项式API,可以用包含多个选项的对象来描述组件的逻辑,如:data、methods、mounted等
组合式API
- setup:是一个标识,告诉Vue需要进行一些处理,让我们可以更简洁的使用组合式API。
- ref():接收一个内部值,返回一个响应式的ref对象,此对象只有一个指向内部值的属性 value。
- onMounted():在组合式API中的钩子方法,注册一个回调函数,在组件挂载完成后执行。
APP.vue
<!-- <script>//写数据export default{data(){return {msg:'上海'}}}
</script> --><script setup>import {ref} from 'vue';//调用ref函数,定义响应式数据const msg = ref('西安')//导入Api.vue文件import ApiVue from './Api.vue'
</script><template><!-- html --><!-- <h1>北京</h1> --><h1>{{ msg }}</h1><br><ApiVue/>
</template><style scoped>/* 样式 */h1{color:red;}
</style>
Api.vue
<script setup>import {onMounted, ref} from 'vue'//声明响应式数据 ref 响应式对象有一个内部的属性valueconst count = ref(0); //在组合式api中,一般需要把数据定义为响应式数据//声明函数function increment(){count.value++;}//声明钩子函数 onMountedonMounted(() => {console.log('vue 已经挂载完毕了...')})
</script><template><!-- html元素 --><button @click="increment">count:{{ count }}</button>
</template><style></style>
案例
使用表格展示所有文章的数据,并完成条件搜索功能
- 钩子函数mounted中,获取所有的文章数据
- 使用v-for指令,把数据渲染到表格上展示
- 使用v-model指令完成表单数据的双向绑定
- 使用v-on指令为搜索按钮绑定单击事件
<script setup>
//导入axios npm install axios
import axios from 'axios';
import { ref } from 'vue';
//定义响应式数据 ref
const articleList = ref([])//发送异步请求,获取所有文章数据
axios.get('http://localhost:8080/article/getAll').then(result => {//把服务器响应的数据保存起来articleList.value = result.data;}).catch(err => {console.log(err);});//定义响应式数据 searchConditionsconst searchConditions = ref({category:'',state:''})//声明search函数const search = function(){//发送请求,完成搜索axios.get('http://localhost:8080/article/search', {params:{...searchConditions.value}}).then(result => {articleList.value = result.data}).catch(err => {console.log(err);})}
</script><template><!-- html元素 --><div>文章分类: <input type="text" v-model="searchConditions.category">发布状态: <input type="text" v-model="searchConditions.state"><button v-on:click="search">搜索</button><br /><br /><table border="1 solid" colspa="0" cellspacing="0"><tr><th>文章标题</th><th>分类</th><th>发表时间</th><th>状态</th><th>操作</th></tr><tr v-for="(article, index) in articleList"><td>{{ article.title }}</td><td>{{ article.category }}</td><td>{{ article.time }}</td><td>{{ article.state }}</td><td><button>编辑</button><button>删除</button></td></tr></table></div></template>
接口调用的js代码一般会封装到.js文件中,并且以函数的形式暴露给外部
优化后的代码:
首先在src目录下创建api文件夹,然后创建js文件
article.js
//导入axios npm install axios
import axios from "axios";//获取所有文章数据的函数export async function articleGetAllService() {//发送异步请求,获取所有文章数据//同步等待服务器响应的结果,并返回 async awaitreturn await axios.get("http://localhost:8080/article/getAll").then((result) => {return result.data;}).catch((err) => {console.log(err);});
}//根据文章分类和发布状态搜索的函数
export async function articleSearchService(conditions) {//发送请求,完成搜索return await axios.get("http://localhost:8080/article/search", {params: conditions,}).then((result) => {return result.data;}).catch((err) => {console.log(err);});
}
Article.vue
<script setup>
import { articleGetAllService, articleSearchService } from '@/api/article.js';
import { ref } from 'vue';
//定义响应式数据 ref
const articleList = ref([])//获取所有文章数据
//同步获取articleGetAllService的返回结果 async await
const getAllArticle = async function () {let data = await articleGetAllService();articleList.value = data;
}getAllArticle();//定义响应式数据 searchConditions
const searchConditions = ref({category: '',state: ''
})//声明search函数
const search = async function () {//文章搜索let data = await articleSearchService({ ...searchConditions.value });articleList.value = data;
}
</script><template><!-- html元素 --><div>文章分类: <input type="text" v-model="searchConditions.category">发布状态: <input type="text" v-model="searchConditions.state"><button v-on:click="search">搜索</button><br /><br /><table border="1 solid" colspa="0" cellspacing="0"><tr><th>文章标题</th><th>分类</th><th>发表时间</th><th>状态</th><th>操作</th></tr><tr v-for="(article, index) in articleList"><td>{{ article.title }}</td><td>{{ article.category }}</td><td>{{ article.time }}</td><td>{{ article.state }}</td><td><button>编辑</button><button>删除</button></td></tr></table></div></template>
**注意:**使用```async``…await
同步接受网路请求的结果
继续优化代码… -> 优化url
article.js
//导入axios npm install axios
import axios from "axios";
//定义一个变量,记录公共的前缀, baseURL
const baseURL = 'http://localhost:8080';
const instance = axios.create({baseURL})//获取所有文章数据的函数export async function articleGetAllService() {//发送异步请求,获取所有文章数据//同步等待服务器响应的结果,并返回 async awaitreturn await instance.get("/article/getAll").then((result) => {return result.data;}).catch((err) => {console.log(err);});
}//根据文章分类和发布状态搜索的函数
export async function articleSearchService(conditions) {//发送请求,完成搜索return await instance.get("/article/search", {params: conditions,}).then((result) => {return result.data;}).catch((err) => {console.log(err);});
}
优化优化再优化…
拦截器
在请求或响应被then或catch处理前拦截他们
在src目录下创建util文件夹新建js
src/Article.vue
<script setup>
import { articleGetAllService, articleSearchService } from '@/api/article.js';
import { ref } from 'vue';
//定义响应式数据 ref
const articleList = ref([])//获取所有文章数据
//同步获取articleGetAllService的返回结果 async await
const getAllArticle = async function () {let data = await articleGetAllService();articleList.value = data;
}getAllArticle();//定义响应式数据 searchConditions
const searchConditions = ref({category: '',state: ''
})//声明search函数
const search = async function () {//文章搜索let data = await articleSearchService({ ...searchConditions.value });articleList.value = data;
}
</script><template><!-- html元素 --><div>文章分类: <input type="text" v-model="searchConditions.category">发布状态: <input type="text" v-model="searchConditions.state"><button v-on:click="search">搜索</button><br /><br /><table border="1 solid" colspa="0" cellspacing="0"><tr><th>文章标题</th><th>分类</th><th>发表时间</th><th>状态</th><th>操作</th></tr><tr v-for="(article, index) in articleList"><td>{{ article.title }}</td><td>{{ article.category }}</td><td>{{ article.time }}</td><td>{{ article.state }}</td><td><button>编辑</button><button>删除</button></td></tr></table></div></template>
src/api/article.js
/* //导入axios npm install axios
import axios from "axios";
//定义一个变量,记录公共的前缀, baseURL
const baseURL = 'http://localhost:8080';
const instance = axios.create({baseURL}) */import requst from "@/util/request.js";export function articleGetAllService() {return requst.get("/article/getAll");
}//根据文章分类和发布状态搜索的函数
export function articleSearchService(conditions) {return requst.get("/article/search", { params: conditions });
}
src/util/request.js
//定制请求的实例//导入axios npm install axios
import axios from "axios";
//定义一个变量,记录公共的前缀, baseURL
const baseURL = 'http://localhost:8080';
const instance = axios.create({baseURL})//添加响应拦截器
instance.interceptors.response.use(result => {return result.data;},err => {alert('服务异常')return Promise.reject(err); //异步的状态会转化为失败的状态}
)export default instance;
Element Plus
- Element:是饿了么团队研发的,基于 Vue3,面相设计师和开发者的组件库
- 组件:组成网页的部件,例如 超链接、按钮、图片、表格、表单、分页条等等
- 官网:https://element-plus.org/zh-CN/
快速入门
-
准备工作:
-
创建一个工程化的vue项目
-
参照官方文档,安装Element Plus组件库(在当前工程的目录下):
npm install element-plus --save
-
main.js中引入Element Plus组件库(参照官方文档)
import { createApp } from 'vue' //导入Vue import ElementPlus from 'element-plus' //导入element-plus import 'element-plus/dist/index.css'//导入element-plus样式 import App from './App.vue'//导入app.vueconst app = createApp(App)//创建应用实例app.use(ElementPlus)//使用element-plus app.mount('#app')//控制html元素
-
-
制作组件:
- 访问Element官方文档,复制组件代码,调整
常用组件
以下图展示为案例
<script lang="ts" setup>import { reactive } from 'vue'const formInline = reactive({user: '',region: '',date: '',
})const onSubmit = () => {console.log('submit!')
}import { ref } from 'vue'const currentPage4 = ref(1)
const pageSize4 = ref(5)
const size = ref<ComponentSize>('default')
const background = ref(false)
const disabled = ref(false)
const total = ref(20)const handleSizeChange = (val: number) => {console.log(`${val} items per page`)
}
const handleCurrentChange = (val: number) => {console.log(`current page: ${val}`)
}import {Delete,Edit,
} from '@element-plus/icons-vue'const tableData = [{title: '标题1',category: '时事',time: '2000-10-10',state: '已发布',},{title: '标题1',category: '时事',time: '2000-10-10',state: '已发布',},{title: '标题1',category: '时事',time: '2000-10-10',state: '已发布',},{title: '标题1',category: '时事',time: '2000-10-10',state: '已发布',},{title: '标题1',category: '时事',time: '2000-10-10',state: '已发布',}
]
</script>
<template><el-card class="box-card"><div class="card-header"><span>文章管理</span><el-button type="primary">发布文章</el-button></div><div style="margin-top: 20px;"><hr></div><el-form :inline="true" :model="formInline" class="demo-form-inline"><el-form-item label="文章分类"><el-select v-model="formInline.region" placeholder="----请选择----" clearable><el-option label="时事" value="时事" /><el-option label="篮球" value="篮球" /></el-select></el-form-item><el-form-item label="发布状态"><el-select v-model="formInline.region" placeholder="----请选择----" clearable><el-option label="已发布" value="已发布" /><el-option label="草稿" value="草稿" /></el-select></el-form-item><el-form-item><el-button type="primary" @click="onSubmit">搜索</el-button></el-form-item><el-form-item><el-button type="default" @click="onSubmit">重置</el-button></el-form-item></el-form><el-table :data="tableData" style="width: 100%"><el-table-column prop="title" label="文章标题" /><el-table-column prop="category" label="分类" /><el-table-column prop="time" label="发表时间" /><el-table-column prop="state" label="状态" /><el-table-column label="操作" width="180"><div><el-button type="primary" :icon="Edit" circle /><el-button type="danger" :icon="Delete" circle /></div></el-table-column></el-table><div class="demo-pagination-block"><el-pagination class="el-p" v-model:current-page="currentPage4" v-model:page-size="pageSize4":page-sizes="[5, 10, 15, 20]" :size="size" :disabled="disabled" :background="background"layout="jumper, total, sizes, prev, pager, next " :total="20" @size-change="handleSizeChange"@current-change="handleCurrentChange" /></div></el-card></template><style scoped>
.el-p {margin-top: 20px;display: flex;justify-content: flex-end;
}.demo-form-inline .el-input {--el-input-width: 220px;
}.demo-form-inline .el-select {--el-select-width: 220px;
}.card-header {display: flex;justify-content: space-between;}
</style>
以下内容为苍穹外卖项目中的前端开发部分
基于脚手架创建前端工程
环境要求:
- node.js 前端项目的运行环境
- npm JavaScript的包管理工具
- Vue CLI 基于Vue进行快速开发的完整系统,实现交互式的项目脚手架
使用Vue CLI创建前端工程:
- 方式一:vue create 项目名称
vue create 项目名称
如果版本报错则依次执行以下命令
npm uninstall -g vue-cli
npm install -g @vue/cli
正常创建后进入如下界面
选中vue3后直接回车即可,出现以下界面则创建成功
- 方式二:vue ui
vue ui
接着弹出一个网页
按以下步骤创建项目
目录结构:
项目结构:
输入以下命令,启动vue服务
npm run serve
访问http://localhost:8080/即可进入网页
前端项目启动后,服务端口默认为8080,很容易和后端tomcat端口号冲突。如何修改前端服务的端口号?
在vue.config.js中配置前端服务端口号:
const { defineConfig } = require("@vue/cli-service");
module.exports = defineConfig({transpileDependencies: true,devServer: {port: 7070,},
});
Vue基本使用方式
vue组件
Vue的组件文件以.vue
结尾,每个组件由三部分组成:
文本插值
- 作用:用来绑定data方法返回的对象属性
- 用法:{{}}
属性绑定
- 作用:为标签的属性绑定data方法中返回的属性
- 用法:
v-bind:xxx
简写为:xxx
事件绑定
- 作用:为元素绑定对应的事件
- 用法:
v-on:xxx
,简写为@xxx
双向绑定
- 作用:表单输入项和data方法中的属性进行绑定,任意一方改变都会同步给另一方
- 用法:
v-model
条件渲染
- 作用:根据表达式的值来动态渲染页面元素
- 用法:
v-if
、v-else
、v-else-if
axios
Axios是一个基于promise 的网络请求库,作用于浏览器和node.js中
安装命令:
npm install axios
导入命令:
import axios from 'axios'
axios的API列表
为了解决跨域问题,可以在vue.config.js文件中配置代理:
axios的post、get方法示例:
axios统一使用方式:axios(config)
综合代码
<template><div class="hello"><div><input type="text" v-bind:value="name" /></div><div><input type="text" :value="age" /></div><input type="text" v-model="name" /><input type="button" v-on:click="handleSave" value="改变" /><div v-if="sex == 1">男</div><div v-else-if="sex == 2">女</div><div v-else>未知</div><input type="button" value="发送POST请求" @click="handleSendPOST"/><input type="button" value="发送GET请求" @click="handleSendGET"/><input type="button" value="统一请求方式" @click="handleSend"/></div>
</template><script>
import axios from 'axios'export default {name: 'HelloWorld',props: {msg: String},data() {return {name: '张三',age: 70,src: 'https://picsfrompicgo.oss-cn-shanghai.aliyuncs.com/202408032351664.png',sex: 3}},methods: {handleSave() {this.name = '李四'},handleSendPOST() {//通过axios发送http请求axios.post('/api/admin/employee/login', {username: 'admin',password: '123456'}).then(res => {console.log(res.data)}).catch(err => {console.log(err.response)})},handleSendGET(){axios.get('/api/admin/shop/status', {headers: {token: 'eyJhbGciOiJIUzI1NiJ9.eyJlbXBJZCI6MSwiZXhwIjoxNzIzNDUzMDIxfQ.h7_MyqtSVw1Yn9xkO7BYutV9VFWNloDe5tzekvw4X98'}}).then(res => {console.log(res.data)})},handleSend(){axios({method: 'post',url: '/api/admin/employee/login',data: {username: 'admin',password: '123456'}}).then(res => {console.log(res.data.data.token)axios({method: 'get',url: '/api/admin/shop/status',headers: {token: res.data.data.token}})})}},
}
</script><style scoped></style>
路由Vue-Router
Vue-Router介绍
vue属于单页面应用,所谓的路由,就是根据浏览器路径不同,用不同的视图组件替换这个页面内容
基于Vue CLI创建带有路由功能的前端项目
-
命令
vue ui
已有项目创建vue-router输入命令
npm install vue-router
接下来是创建过程
耐心等待创建即可
- 效果展示
路由配置
- 路由组成
- VueRouter:路由器,根据路由请求在路由视图中动态渲染对应的视图组件
- <router-link>:路由链接组件,浏览器会解析成<a>
- <router-view>:路由视图组件,用来展示与路由路径匹配的视图组件
- 路由路径和路由视图对于关系
- <router-link>
- <router-view>
-
路由跳转
- 标签式
- 编程式
如何用户访问的路由地址不存在,该如何处理?
嵌套路由
- 嵌套路由:组件内要切换内容,就需要用到嵌套路由(子路由)
-
实现步骤
-
安装并导入ElementUI,实现页面布局(Container布局容器)—ContainerView.vue
npm i element-ui -S
-
提供子视图组件,用于效果展示 —P1View.vue、P2View.vue、P3View.vue
-
在src/router/index.js中配置路由映射规则(嵌套路由配置)
-
在布局容器视图中添加<router-view>,实现子视图组件展示
-
在布局容器中添加<router-link>,实现路由请求
-
注意::子路由变化,切换的是【ContainerView组件】中<router-view\>\</router-view>
部分的内容
ContainerView.vue
<template><el-container><el-header>Header</el-header><el-container><el-aside width="200px"><router-link to="/c/p1">P1</router-link><br><router-link to="/c/p2">P2</router-link><br><router-link to="/c/p3">P3</router-link></el-aside><el-main><router-view /></el-main></el-container></el-container>
</template><script>
export default {}
</script><style>
.el-header,
.el-footer {background-color: #B3C0D1;color: #333;text-align: center;line-height: 60px;
}.el-aside {background-color: #D3DCE6;color: #333;text-align: center;line-height: 200px;
}.el-main {background-color: #E9EEF3;color: #333;text-align: center;line-height: 160px;
}body>.el-container {margin-bottom: 40px;
}.el-container:nth-child(5) .el-aside,
.el-container:nth-child(6) .el-aside {line-height: 260px;
}.el-container:nth-child(7) .el-aside {line-height: 320px;
}
</style>
index.js
import Vue from "vue";
import VueRouter from "vue-router";
import HomeView from "../views/HomeView.vue";Vue.use(VueRouter);//维护路由表,某个路由路径对应哪个视图组件
const routes = [{path: "/", //路由路径name: "home",component: HomeView,},{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"),},{path: "/404",component: () => import("../views/404View.vue"),},{path: "*",redirect: "/404",},{path: "/c",component: () => import("../views/container/ContainerView.vue"),redirect: '/c/p1', //重定向,当访问/c时,直接重定向到 /c/p1//嵌套路由(子路由),对应的组件会展示在当前组件内部children: [{path: "/c/p1",component: () => import("../views/container/P1View.vue"),},{path: "/c/p2",component: () => import("../views/container/P2View.vue"),},{path: "/c/p3",component: () => import("../views/container/P3View.vue"),},],},
];const router = new VueRouter({routes,
});export default router;
App.vue
<template><div id="app"><nav><router-link to="/">Home</router-link> |<router-link to="/about">About</router-link> | <router-link to="/test">Test</router-link> | <input type="button" value="编程式路由跳转" @click="jump()" /></nav><!-- 不同的视图组件展示的位置 --><router-view /></div>
</template><script>
export default {methods: {jump() {this.$router.push("/about")}},
}
</script><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>
P1View.vue
<template><div>这是P1 View</div>
</template><script>
export default {}
</script><style></style>
状态管理Vuex
Vuex介绍
- vuex是一个专为Vue.js应用程序开发的状态管理库
- vuex是可以在多个组件之间共享数据,并且共享的数据都是响应式的,即数据的变更能及时渲染到模板
- vuex采用集中存储管理所有组件的状态
核心概念
- state:状态对象,集中定义各个组件共享的数据
- mutations:类似于一个事件,用于修改共享数据,要求必须是同步函数
- actions:类似于mutation,可以包含异步操作,通过可以调用mutation来改变共享数据
使用方式
- 创建带有vuex功能的脚手架工程
- 定义和展示共享数据
- 在mutations中定义函数,修改共享数据
- App.vue中调用mutations中的函数代码
<template><div id="app">欢迎你,{{ $store.state.name }}<input type="button" value="通过mutations修改共享数据" @click="handleUpdate"/><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},methods: {handleUpdate(){//mutations中定义的函数不能直接调用,必须通过这种方式来调用//setName为mutations中定义的函数名称,张三为传递的参数this.$store.commit('setName', '张三')}},
}
</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>
- 在action中定义函数,用于调用mutation
在App.vue中调用actions中的函数代码:
<template><div id="app">欢迎你,{{ $store.state.name }}<input type="button" value="通过mutations修改共享数据" @click="handleUpdate" /><input type="button" value="调用actions中定义的函数" @click="handleCallAction" /><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},methods: {handleUpdate() {//mutations中定义的函数不能直接调用,必须通过这种方式来调用//setName为mutations中定义的函数名称,张三为传递的参数this.$store.commit('setName', '张三')},handleCallAction() {//调用actions中定义的函数,setNameByAxios为函数名称this.$store.dispatch('setNameByAxios')}},
}
</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>
TypeScript
TypeScript介绍
- TypeScript(简称:TS)是微软推出的开源语言
- TypeScript是JavaScript的超集(JS有的TS都有)
- TypeScript = Type + JavaScript(在JS基础上增加了类型支持)
- TypeScript文件扩展名为ts
- TypeScript可编译成标准的JavaScript,并且在编译时进行类型检查
安装TypeScript
npm install -g typescript
- TypeScript简单体验,创建hello.ts文件,内容如下
- TS为什么要增加类型支持?
- TS 属于静态类型编程语言,JS 属于动态类型编程语言
- 静态类型在编译期做类型检查,动态类型在执行期做类型检查
- 对于JS来说,需要等到代码执行的时候才发现错误(晚)
- 对于TS来说,在代码编译的时候就可以发现错误(早)
- 配合 VScode 开发工具,TS 可以提前到在编写代码的同时就发现代码中的错误,减少找Bug、改Bug的时间
TypeScript常用类型
- 创建前端工程,基于TypeScript开发
- 类型标注的位置
- 标注变量
- 标注参数
- 标注返回值
- 字符串类型、数字类型、布尔类型
//字符串类型
let username: string = 'itcast'//数字类型
let age: number = 20//布尔类型
let isTrue: boolean = trueconsole.log(username)
console.log(age)
console.log(isTrue)
- 字面量类型(类似于枚举)
**注意:**字面量类型用于限定数据的取值范围
- interface类型
**小技巧:**可以通过在属性名后面加上? ,表示当前属性为可选
- class类–基本使用
**注意:**使用class关键字来定义类,类中可以包含属性、构造方法、普通方法
- class类–实现接口
- class类–类的继承