我们要学习他的原因其实有很多点,必须说简单易学,学习成本低,应用场景多,很多项目也都是用Vue来实现的。Vue社区也比较繁荣,所以Vue的选择应该是前端人员选择学习最优先的,最重要的原因就是–企业要用它!!!
vue是什么
Vue是前端优秀框架(MVVM),是一套用于用于构建用于页面的渐进式框架
为什么要学习Vue
- Vue是目前前端最火的框架之一
- Vue是目前企业技术栈中要求的知识点
- Vue 可以提升开发体验
- Vue学习难度较低
vue2官网
vue3官网
vue cli官网
Vue CLI 是Vue开发的标准工具,Vue CLI是一个基于Vue。js进行快速开发的完整系统。可以一键创建vue的开发环境
在官网进入cli=>生态系统=>官方项目下面=>vue cli
安装
npm install -g @vue/cli
安装之后,你就可以在命令行中访问vue命令。你可以通过简单运行vue,看看是否展示出了一份所有可用命令的帮助信息,来验证他是否安装成功
vue --version
运行以下命令来创建一个新项目
vue create vue-demo
注意创建项目名字不能存在大写,可以用-连接多个单词
温馨提示:
- 在控制台中,可以用上下按键调整选择项
- 在控制台中,可以用空格(spacebar)选择是否选中和取消选中
可以选择默认项目模板,或者选"手动选择特性"来选择需要的特性。
我们选择Babel和Peogressive Web App(PWA) Support俩个选项即可
温馨提示:
在学习期间,不要选中Linter/Fomatter,以避免不必要的错误提示
vue目前有俩大主流大版本vue2和vue3,我选择vue3最新版本
配置放在哪里? In dedicated config files专用配置文件或者Inpackage.json在package.json文件
将其桃村为未来项目的预置?y代表保存,并添加名字,n不保存
选n即可,因为日后这个选项会改了,会增加更多内容
项目创建成功如下提示信息
运行项目
第一步: 进入项目根目录 cd 项目文件夹名称=>我这里是
cd vue-demo
第二步:运行 npm run serve 启动项目
npm run serve
运行成功,在游览器属于地址启动项目
项目文件目录
文件目录介绍
vue官网模板语法
数据绑定最常见的形式就是使用"Mustache"(双大括号)语法的文本插值
<span>Message: {{ msg }}span>
一般配合js中 data()设置数据
export default {
name: 'HelloWorld',
data(){
return{
message:'demo'
}
}
}
双大括号会将数据解释为普通文本,而非HTML代码。为了输出真正的HTML,你需要使用v-html指令
<div>{{ rawHtml }}div>
<div v-html="rawHtml">div>
data(){
return{
rawHtml:"百度"
}
}
Mustache 语法不能在HTML属性中使用,然而人,可以使用v-bind指令
<div v-bind:id="cId">binddiv>
<div :id="cId">binddiv>
data(){
return{
cId:1001
}
}
温馨提示:
v-bind 可以简写成 :
在我们的模块中,我们一直都只绑定简单的propetry键值,vue.js都提供了完全的JavaScript表达式支持
{{number+1}}
{{ok?'yes':''no}}
{{}message.split('').reverse().join('')}
这些表达式会在当前活动实例的数据作用域下作为JavaScript被解析。有个限制就是,每个绑定都只能包含单个表达式,所以下面这些例子都不会生效
<!-- 这是语句,不是表达式 -->
{{var a=1}}
<!-- 流程控制也不会生效,请使用三元表达式 -->
{{if(ok){return message}}}
v-if指令用于条件性地渲染一块内容。这块内容只会在指令的表达式返回true值的时候被渲染。
<p v-if="flag">我是要成为海贼王的男人--路飞p>
data(){
return{
flag:true
}
}
你可以使用v-else来表示v-if的else块
<p v-if="flag">我是要成为海贼王的男人--路飞p>
<p v-else>路飞p>
data(){
return{
flag:false
}
}
另一个用于条件性展示元素的选项式v-show指令
<p v-show="flag">我是要成为海贼王的男人--路飞p>
data(){
return{
flag:true
}
}
也是经典的面试题
用v-for把一个数组映射为一组元素
我们可以用v-for指令基于一个数组来渲染一个列表。v-for指令需要使用item in items形式的特殊语法,其中items是原数据数组,而item则是被迭代的数组元素的别名
<ul>
<li v-for="item in newsList">{{ item.title }}li>
ul>
data(){
return{
newsList:[
{
id:1001,
title:'新闻头条1'
},
{
id:1002,
title:'新闻头条2'
},
{
id:1003,
title:'新闻头条3'
},
]
}
}
<ul>
<li v-for="item in newsList" :key="item.id">{{ item.title }}li>
ul>
<ul>
<li v-for="{item,index} in newsList" :key="index">{{ item.title }}li>
//数据没有id,可以用index下面绑定key
ul>
我们可以使用v-on指令(通常缩写为@符号)来监听DOM事件,并在触发事件时执行一些JavaScript。用法为v-on:click='methodName’或使用快捷方式@click=“methodName”
<button v-on:click="num+=1">点击:{{ num }}button>
<button @click="num+=1">点击:{{ num }}button>
data(){
return{
num:0
}
}
然而许多事件处理逻辑会更为复杂,所以直接把JavaScript代码写在v-on指令中是不可行的。因此v-on还可以接收一个需要调用的方法名称。
<button @click="clickHandle">按钮button>
<p>{{ message }}p>
data(){
return{
num:0,
message:'消息通知'
}
},
methods:{
clickHandle(e){
//在事件中,读取data中的属性,是需要通过this.属性
this.message='消息被撤回了'
console.log(e)
// e是原生DOM event
e.target.innerHTML='点击之后'
}
}
这是官方的翻译称呼,其实我们可以直接叫他“事件传递函数”
<button @click="say('hi')">say hibutton>
<button @click="say('what')">say whatbutton>
methods:{
say(data){
console.log(data)
}
}
}
<ul>
<li v-for="item in names
" @click="clickItemHandle(item)">{{ item }}li>
ul>
data(){
return{
names:['路飞','索隆','乔巴']
}
},
methods:{
clickItemHandle(item){
console.log(item)
}
}
你可以用v-model指令在表单input、textarea及select元素上创建双向数据绑定。它会根据控件类型自动选取正确的方法来更新元素。尽管有些神奇,但v-model本质上不过是语法糖。它负责监听用户的输入事件来更新数据,并在某种极端场景下进行一些特殊处理。
<input type="text" v-model="useName">
<input type="text" v-model="password">
<p>{{ useName }},{{ password }}p>
<button @click="clickGetUserName">获取用户名button>
data(){
return{
useName:"",
password:""
}
},
methods:{
clickGetUserName(){
console.log(this.useName)
}
}
lazy: 在默认情况下,v-model在每次input事件触发后将输入框的值与数据进行同步,你可以添加lazy修饰符,从而转为change事件之后进行同步=>或者或失去焦点时=>减少性能消耗
<input type="text" v-model.lazy="useName">
.trim:
如果要自动过滤用户输入的首尾空白符,可以给v-model添加trim修饰符
<input type="text" v-model.trim="password">
vue单文件组件(又名==.vue文件==,缩写SFC)是一种特殊的文件格式,它允许将vue组件的 teplate => 模板、 script =>逻辑与 style => 样式封装在单个文件中
<template>
<div class="hello">
<h3>单文件组件h3>
div>
template>
<script>
export default {
// innerHTML innerText
name: 'HelloWorld',
data(){
return{
}
},
methods:{
}
}
script>
<style scoped>
h3{
color:red
}
style>
组件与组件之间是需要存在交互的,否则完全没关系,组件的意义就很小了
prop是你可以在组件上注册的一些自定义attribute
从父组件传递
<pop1 :title="title" :age="age" :names="names"/>
data(){
return{
title:'我是一个标题',
age:20,
names:['路飞','索隆']
}
},
从子组件接收
<p>{{ title }}p>
<p>{{ age }}p>
<ul>
<li v-for="(item,index) in names" :key="index">{{ item }}li>
ul>
export default{
name:'pop1',
props:{
title:{
type:String,
// 接收值的类型
default:''
// 默认值
},
age:{
type:Number,
default:''
},
names:{
type:Array,
// 数组和对象必须使用函数进行返回
default:function(){
return []
}
}
}
}
Props传递参数其实是没有类型限制的
温馨提示
数据类型为数组或者对象的时候,默认值是需要返回工厂模式(工厂模式=>函数模式)
Props:{
title:String,
likes:Number,
isPublished:Boolean,
commentIds:Array,
author:Object,
callback:Function
}
自定义事件可以在组件中反向传递数据,prop可以将数据从父组件传递到子组件,那么反向如何操作呢,就可以利用自定义事件实现 $emit
从子组件通过自定义事件向父组件传递数据
<button @click="sendClickHandle">点击向父组件传递数据button>
data(){
return{
message:'我是emits组件数据'
}
},
methods:{
sendClickHandle(){
// 参数1:字符串:理论上是随便的,但是需要具有意义
// 参数2:传递的数据
this.$emit('onEvent',this.message)
}
父组件接收数据
<emits @onEvent="getDateHandle" />
<p>{{ message }}p>
data(){
return{
//先定义一个接收数据的字段
message:'',
}
},
methods:{
//自定义的事件
getDateHandle(data){
console.log(data)
this.message=data
}
}
每个组件在被创建时都要经历一系列的初始化1过程一一例如,需要设置数据监听,编译模板、将实例挂载到DOM并在数据变化时更新DOM等,同时在这个过程中也会运行一些叫做生命周期钩子的函数,这给了用户在不同阶段添加自己的代码的机会
下方是vue官方生命周期图示=>所有红色框都输入vue的生命周期
一定要记住,这也是面试和前端必须掌握的
为了方便记忆,我将它们进行了一下分类:
export default {
data() {
return {
message: ''
}
},
// 创建时
beforeCreate() {
console.log('beforeCreate:组件创建之前');
},
created() {
console.log('created:组件创建完成');
},
// 渲染时
beforeMount() {
console.log('beforeMount:组件渲染之前');
},
mounted() {
console.log('mounted:组件渲染完成');
//把网络请求放到这里
},
// 更新时
beforeUpdate(){
console.log('beforeUpdate:组件更新之前');
},
updated(){
console.log('updated:组件更新完成');
},
// 销毁时
beforeUnmount(){
console.log('beforeUnmount:组件卸载之前');
//卸载之前,把消耗性能的处理都干掉
//比如定时器
},
unmounted(){
console.log('unmounted:组件卸载完成');
}
}
运行顺序
组件创建完成就会执行这四个声明周期=>如控制台打印所示:
页面发生变化执行的生命周期=>如控制台打印所示:
组件销毁时执行的生命周期,这里就先不给大家测试了,等后续用到我会写在文档中,总而言之,这些生命周期大家日后根据自己项目的业务逻辑进行熟悉,这里先做一些简单的了解
// 销毁时
beforeUnmount(){
console.log('beforeUnmount:组件卸载之前');
},
unmounted(){
console.log('unmounted:组件卸载完成');
}
关于大家在日常开发中有一些需求,可以在github上搜和vue官网推的
温馨提示
GitHub
另外一个就是vue官网整合的一些比较好的第三方
温馨提示
Vue2官网
注意一定要注意自己使用vue的版本,并不是每个都可以用的,一定要找版本对应的
温馨提示
Swiper官方文档
在vue中使用Swiper官方文档
npm i swiper--save
//在终端安装
npm i [email protected]
//安装指定版本
<template>
<div>
<Swiper>
<SwiperSlide>
图片1
SwiperSlide>
<SwiperSlide>
图片2
SwiperSlide>
<SwiperSlide>
图片3
SwiperSlide>
Swiper>
div>
template>
<script>
import { Swiper, SwiperSlide } from 'swiper/vue';
// 引入Swiper
import 'swiper/css';
// 引入样式
export default{
name:'lb',
components:{
Swiper,
SwiperSlide
},
data(){
return{
}
}
}
script>
<style scoped>
style>
<template>
<div>
<Swiper :modules="modules" :pagination="{ clickable: true }">
<SwiperSlide>
<img src="图片地址" alt="">
SwiperSlide>
<SwiperSlide>
<img src="" alt="">
SwiperSlide>
<SwiperSlide>
<img src="" alt="">
SwiperSlide>
Swiper>
div>
template>
<script>
import { Swiper, SwiperSlide } from 'swiper/vue';
// 引入Swiper
import 'swiper/css';
// 引入样式
import { Pagination} from 'swiper';
// 引入指示器
import 'swiper/css/pagination';
// 引入指示器样式
export default{
name:'lb',
components:{
Swiper,
SwiperSlide
},
data(){
return{
modules:[Pagination]
}
}
}
script>
<style scoped>
style>
☞Axios官方API
☞看云–Axios文档
Axios是一个基于Promise的网络请求库
Axios的应用是需要单独安装的
npm install --save axios
组件中引入:
import axios from "axios"
<p>{{ chengpin.title }}p>
import axios from 'axios'
// 引入axios
export default{
name:'axiosob',
mounted(){
console.log('mounted:组件渲染完成');
//把网络请求放到这里
// get请求方式
axios({
method:'get',
// 请求方式
url:'http://iwenwiki.com/api/blueberrypai/getChengpinDetails.php'
// 请求地址
}).then(res=>{
console.log(res.data)
this.chengpin=res.data.chengpinDetails[0]
// 取数据
})
},
data(){
return{
chengpin:{}
//用来接受请求的数据
}
}
}
axios.get('http://iwenwiki.com/api/blueberrypai/getChengpinDetails.php').then(res=>{
console.log(res.data)
this.chengpin=res.data.chengpinDetails[0]
// 取数据
})
import axios from 'axios'
// 引入axios
export default{
name:'axiosob',
mounted(){
console.log('mounted:组件渲染完成');
//把网络请求放到这里
// post请求方式
axios({
method:'post',
// 请求方式
url:'http://iwenwiki.com/api/blueberrypai/login.php',
// 请求地址
data:{
user_id:'[email protected]',
password:'iwen123',
verification_code:'crfvw'
}
// data是向后端接口传递的数据,可以数据实际工作中一定要根据后端给的文档规范传
}).then(res=>{
// 取数据
console.log(res.data)
})
},
data(){
return{
}
}
}
post请求向后端传递数据时,可能会遇到格式的问题,转字符串可以用以下第三方插件,可能已经过时了,这种第三方有很多,像qs等等
温馨提示
post请求参数需要额外处理的
- 转依赖:npm install --save querystring
- 转换参数格式:querystring.stringify({})
npm install --save querystring
安装完成,在组件中引用
import querystring from 'querystring'
使用querystring
// post请求方式
axios({
method:'post',
// 请求方式
url:'http://iwenwiki.com/api/blueberrypai/login.php',
// 请求地址
data:querystring.stringify({
user_id:'[email protected]',
password:'iwen123',
verification_code:'crfvw'
})
// data是向后端接口传递的数据,可以数据实际工作中一定要根据后端给的文档规范传
}).then(res=>{
// 取数据
console.log(res.data)
})
使用后这样就没问题了
axios.post('http://iwenwiki.com/api/blueberrypai/login.php',querystring.stringify({
user_id: '[email protected]',
password: 'iwen123',
verification_code: 'crfvw'
})).then(res=>{
console.log(res.data)
})
},
在main.js主入口文件引入
import { createApp } from 'vue'
import App from './App.vue'
import './registerServiceWorker'
import axios from 'axios'
// 全局引入axios
const app=createApp(App)
app.config.globalProperties.$axios = axios
//axios挂载到全局
app.mount('#app')
在组件中使用就要变一下,例如
this.$axios.get('http://iwenwiki.com/api/blueberrypai/getChengpinDetails.php').then(res => {
console.log(res.data)
this.chengpin = res.data.chengpinDetails[0]
// 取数据
})
☞Axios官方API
☞看云–Axios文档
在日常开发过程中,一个项目中的请求会很多,此时一般采取的方案是网络请求封装起来
在src目录下创建文件夹utils,并创建文件request.js,用来存储网络请求对象axios
import axios from "axios";
// 引入axios
import querystring from "querystring";
// 引入querystring
const errorHandle = (status, info) => {
// errorHandle错误函数
switch (status) {
case 400:
console.log("400--语义错误");
break;
case 401:
console.log("401--服务器认证失败");
break;
case 403:
console.log("403--服务器拒绝访问");
break;
case 404:
console.log("404--地址错误");
break;
case 500:
console.log("500--服务器遇到意外");
break;
case 502:
console.log("502--服务器无响应");
break;
default:
console.log(info);
break;
}
};
const instance = axios.create({
// 网络请求的公共配置
timeout: 5000,
// 请求超时时间最长5秒
});
// 这里最常用的=>拦截器
// 发送数据之前
instance.interceptors.request.use(
(config) => {
// config=>发送数据成功的函数
if (config.method === "post") {
config.data = querystring.stringify(config.data);
// 格式化post传递参数的格式
}
// config:包含着网络请求的所有信息
return config;
},
(error) => {
// error=>发送数据失败的函数
return Promise.reject(error);
// 把失败的信息返回出去
}
);
// 获取之前
instance.interceptors.response.use(
(response) => {
// response=>获取成功的函数
return response.status === 200
? Promise.resolve(response)
: Promise.reject(response);
// response.status=>状态码
},
(error) => {
// error=>获取数据失败的函数,错误的处理才是需要关注的
const { response } = error;
// response这里指错误的信息
errorHandle(response.status,response.info)
}
);
export default instance;
在src目录下创建文件夹api,并创建文件==path.js(或base.js)用来设置路径
const base={
// base把所有的路径都放在这里
baseUrl:'http://iwenwiki.com',
// baseUrl=>公共路径
chengpin:'/api/blueberrypai/getChengpinDetails.php'
// chengpin成品地址
}
export default base
在src目录下创建文件夹api,并创建文件index.js调接口的文件
// 把所有网络请求的方法都放在这个文件
import axios from "../utils/request"
// 引入封装好的request文件
import path from'./path'
// 引入path路径文件
const api={
// 成品详情接口
getChengpin(){
return axios.get(path.baseUrl+path.chengpin)
}
}
export default api
import api from '../api/index'
// 引入调接口文件
export default {
name: 'axiosob',
mounted() {
//使用封装好的方法
api.getChengpin().then(res=>{
console.log(res.data)
})
},
data() {
return {
}
}
}
同源策略是游览器的一项安全策略,游览器只允许js代码请求和当前服务器域名,端口,协议相同的数据接口上的数据,这就是同源策略。
也就是说,当协议、域名、端口任意一个不同时,都会产生跨域问题,所以又应该如何解决跨域问题呢
下方是一个标准的跨域错误
在vue.config.js文件下配置
const { defineConfig } = require('@vue/cli-service')
module.exports = defineConfig({
transpileDependencies: true,
// 下列是解决跨域问题
devServer:{
proxy:{
'/api':{
target:'http://iwenwiki.com/',
// target产生跨域的地址
changeOrigin:true
}
}
}
})
温馨提示
解决完跨域配置之后,要记得重启服务器才行哦!
在vue中,我们可以通过vue-router路由管理页面之间的关系
Vue Router是Vue.js的官方路由。它与Vue.js核心深度集成,让Vue.js构建单页面应用变得轻而易举
npm install --save vue-router
src=>views文件夹=>放一些组件
<template>
<h3>HomeView组件h3>
template>
<template>
<h3>About组件h3>
template>
src=>router路由文件夹=>index文件
// 路由配置文件
//1.引入路由
import { createRouter, createWebHashHistory,createWebHistory } from "vue-router";
// 2.引入页面组件
import HomeView from "../views/HomeView.vue";
import About from "../views/About.vue";
// 页面配置
const routes = [
{
path: "/",
// path访问路径
name: "Home",
component: HomeView,
},
{
path: "/about",
name: "About",
component: About,
},
];
// 配置信息中需要页面的相关配置
const router = createRouter({
// 配置路由
/**
* createWebHashHistory
* http://localhost:8081/#/
* http://localhost:8081/#/about
* 原理:a标签的锚点链接
*/
/**
* createWebHistory
* http://localhost:8081/
* http://localhost:8081/about
* 此种方式需要后台配合做重定向,否则会出现404问题
* 原理:h5 pushState()
*/
history: createWebHashHistory(),
// history访问方式
routes,
});
export default router;
在主入口文件main.js使用以下
import { createApp } from 'vue'
import App from './App.vue'
import './registerServiceWorker'
import router from './router'
// 引入配置好的路由文件
createApp(App).use(router).mount('#app')
// .use(router)进行使用
在页面中使用=>App.vue
<template>
<router-view>
router-view>
<RouterView>RouterView>
template>
<router-link to="/">
首页
router-link>
<router-link to="/about">
关于
router-link>
页面跳转过程中,是可以携带参数的,这也是很常见的业务
例如:在一个列表页,点击进入查看每个列表项的详情
import { createRouter, createWebHashHistory } from 'vue-router'
import HomeView from '../views/HomeView.vue'
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:'/news',
name:'news',
// 新闻列表页
component:()=>import('../views/news.vue')
},
{
path:'/newsDetails/:name',
// 指定参数key
name:'newsDetails',
// 新闻详情页
component:()=>import('../views/newsDetails.vue')
}
]
const router = createRouter({
history: createWebHashHistory(),
routes
})
export default router
在news组件下进行跳转
<template>
<h3>新闻列表页h3>
<ul>
<li><router-link to="/newsDetails/百度新闻"> 百度新闻 router-link>li>
<li><router-link to="/newsDetails/网易头条"> 网易新闻 router-link>li>
<li><router-link to="/newsDetails/头条新闻"> 头条新闻 router-link>li>
ul>
template>
在newsDetails详情页
<template>
<h3>{{$route.params.name}}--新闻详情h3>
template>
路由嵌套是非常常见的需求
router文件下index.js
import { createRouter, createWebHashHistory } from 'vue-router'
import HomeView from '../views/HomeView.vue'
const routes = [
{
path: '/',
name: 'home',
component: HomeView
},
{
path: '/about',
name: 'about',
// name组件名字可加可不加
// 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'),
children:[{
// 子页面路由配置
// 二级导航的路径不要加 /
path:'info',
component:()=>import('../views/AboutSub/AboutInto.vue')
},
{
path:'news',
component:()=>import('../views/AboutSub/AboutNews.vue')
}]
}
]
const router = createRouter({
history: createWebHashHistory(),
routes
})
export default router
about页面
<template>
<div class="about">
<router-link :to="{path:'info'}">关于信息router-link>
| <router-link :to="{path:'news'}">关于新闻router-link>
<router-view>
router-view>
div>
template>
router文件下index.js
{
path: '/about',
name: 'about',
redirect:'/about/info',
// 重定向
// name组件名字可加可不加
// 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'),
children:[{
// 子页面路由配置
// 二级导航的路径不要加 /
path:'info',
component:()=>import('../views/AboutSub/AboutInto.vue')
},
{
path:'news',
component:()=>import('../views/AboutSub/AboutNews.vue')
}]
}
素材联系我
如果这篇【文章】有帮助到你,希望可以给我点个赞,创作不易,如果有对前端端或者对python感兴趣的朋友,请多多关注,咱们一起探讨和努力!!!
个人主页 : 前端初见