目录
Vue简介
Vue (读音 /vjuː/,类似于 view) 是一套用于构建用户界面的渐进式框架。
版本有vue2和vue3
大纲
vue基础
第一个vue程序
{{xxx}}xxx只能写js表达式(就是这个表达式最后解析后返回一个值的),xxx会到data中识别所有属性。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>hello world-vue</title>
<!-- 引入vue.js,开发环境版本,包含了有帮助的命令行警告 -->
<!-- <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script> -->
<script src="../js/vue.js"></script>
</head>
<body>
<!-- 一个模板 -->
<div id="app">
{{ message }}
</div>
<script>
Vue.config.productionTip = false;
// 创建一个Vue实例
var app = new Vue({
// el:'元素选择器' 将new的Vue实例和Dom元素绑定起来,设置vue实例的挂载点,指定这个Vue实例为谁服务
el: '#app',
// data中用于定义数据,数据供Vue服务的模板使用。
data: {
message: 'hello world!'
}
})
</script>
</body>
</html>
这边要注意vue.js的引入位置,需要在用到vue之前执行,也就是要在new Vue前执行,我第一次放在后面导致vue is not defined报错。
Vue指令
v-text和v-html
vue-cli
vue-router
vuex
element-ui
vue3
----------------------------
el挂载点
语法 el:'元素选择器'
作用 将new的Vue实例和Dom元素绑定起来,设置vue实例的挂载点
作用范围 vue实例只作用于其挂载的的元素以及后代元素。
data数据对象
vue实例的挂载元素中如果有{{}}的话,会被解析并将data对象中的数据渲染进去。
会解析上面的html,一旦解析到有vue的语法,就会自动按照vue的语法将data中的数据渲染进去。
<body>
<div id="app">
<b>一名屌丝的基本信息</b><br>
在干嘛:{{message}}<br>
院校信息:{{school.name}} <br>
爱好:{{interest[1]}}
</div>
<script>
var app = new Vue({
el:"#app",
data:{
// 基本数据类型
message:"学vue第一天",
// 对象
school:{
name:"莆田学院",
address:"莆田市城厢区",
phone:"18120997089"
},
// 数组
interest:["跑步",3,"乒乓球","打游戏"]
}
})
</script>
</body>
el和data的两种写法
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<!-- 引入vue.js,开发环境版本,包含了有帮助的命令行警告 -->
<script src="../js/vue.js"></script>
</head>
<body>
<div id="app">
<h2>{{hello}}</h2>
</div>
<script>
/* // el挂载的两种写法,这两种写法都可以
var app = new Vue({
// 第一种写法
// el:"#app",
data:{
hello:"how are you"
}
})
// 第二种写法 mount挂载
app.$mount("#app"); */
// data的两种写法
var app = new Vue({
el:"#app",
// 第一种写法:对象式
// data:{
// hello:"how are you"
// }
// 第二种写法:函数式,函数的返回值就是data种的属性
// 以后学到组件后,data必须用函数式,由Vue管理的函数,一定不能用箭头函数,否则this就不是代表vue实例了.
data(){
return{
hello:"data函数式"
}
}
})
</script>
</body>
</html>
MVVM
将数据都定义在Model中,View和Model进行数据绑定后,Model中的数据一旦变化,View中有用到data的地方,都会随之发生改变。
View中的一些数据发送改变,也会改变Model中的数据,如v-model。`
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<!-- 引入vue.js,开发环境版本,包含了有帮助的命令行警告 -->
<script src="../js/vue.js"></script>
</head>
<body>
<!--
MVVM
Model:模板,代表Vue实例中的data数据
View:视图,就是我们写的html和css页面
ViewModel:视图模型,就是我们的Vue实例
MVVM模型
1. M:模型(Model) : data中的数据
2. V: 视图(View) :模板代码
3. VM: 视图模型(ViewModel): Vue实例
观察发现:
1. data中所有的属性,最后都出现在了vm身上。)
2.vm身上所有的属性及Vue原型上所有属性,在Vue模板中都可以直接使用。
-->
<!-- view视图 -->
<div id="app">
名字:{{name}}
<br>
地址:{{address}}
</div>
<script>
//
var vm = new Vue({
el:"#app",
data:{
name:"莆田学院",
address:"学园中街1103号"
}
})
console.log("vm",vm)
</script>
</body>
</html>
Vue指令
v-text和v-html
<body>
<!--
v-text 会将标签体的内容全部替换掉,而且只能原封不动的将data中的数据替换标签体,
若只想替换部分内容可以用vue的插值语法{{}}
v-html 也是将标签体中的内容全部替换掉,但是如果data数据中有
html内容,会先解析好后再替换标签体内容。
-->
<div id="app">
<h1 v-text="message+'!'">一段文本</h1>
<h2>{{info+"!"}}一段文本</h2>
<p v-html="content">wen</p>
<p v-text="content">wen</p>
</div>
<script>
var vue = new Vue({
el:"#app",
// 准备一些数据
data:{
message:"hello",
info:"内容",
content:"<a href='https://www.baidu.com/'>百度</a>"
}
})
</script>
</body>
v-on
<body>
<!--
v-on:事件名="方法名" 指令可以给元素绑定事件,当事件触发后,会执行方法。
v-on: 可替换为@
v-on:click 单击事件
-->
<div id="app">
<input type="button" value="提交" v-on:click="method1"></input>
<p v-on:click="showTime">{{time}}</p>
</div>
<script>
var vue = new Vue({
el: "#app",
data: {
time: "点击查看时间"
},
// 定义方法
methods: {
method1: function () {
alert("你要加油!");
console.log("数据:"+this.time);
},
showTime: function () {
// this可以获取到data对象,this.数据名可以操作数据内容,从而改变dom中的内容,不用像以前操作dom元素来修改内容。
var t = new Date();
this.time = t;
}
}
})
</script>
</body>
v-on的补充
<body>
<!--
v-on:事件名='方法名'
对v-on事件绑定的补充:
1.我们可以给事件触发的方法传参数,前提是在方法的定义处需要定义形参来接收我们的实参.
2.事件修饰符
@keyup.enter
@keyup是键盘事件, .enter给事件添加修饰符,就是当回车时才触发,通过'.xxx'来添加事件修饰符.
-->
<div id="app">
<input type="text" @keyup.enter="login('小明')">
<button>登录</button>
</div>
<script>
var app = new Vue({
el:"#app",
data:{
},
methods:{
login(userName){
alert(userName + "登录成功");
}
}
})
</script>
</body>
v-show
<body>
<!--
当v-show后面的表达式值为true时,才显示标签元素,否则隐藏。
表达式可以直接取到data中的数据。
这个原理是操作标签的样式:style="display: none;" 实现元素的隐藏。
-->
<div id="app">
<div>
<img src="../img/monkey.png" v-show="isShow==true">
</div>
<br>
<button @click="showChange">按我</button>
</div>
<script>
var vue = new Vue({
el:"#app",
data:{
isShow:true
},
methods:{
showChange:function(){
this.isShow = !this.isShow;
}
}
})
</script>
</body>
v-if
<body>
<!--
v-if 和v-show效果一样,都是当表达式的值为true时,才显示。
但是原理不同,v-if是直接操作dom树,删除或添加元素到dom树中。
当频繁切换显示,使用v-show,v-if直接操作dom树,开销大。
-->
<div id="app">
<span v-if="temp > 3">hello </span>
<button v-on:click="add">切换显示状态</button>
</div>
<script>
var vue = new Vue({
el: "#app",
data: {
temp: 2
},
mehtods: {
add: function () {
this.temp++;
console.log(this.temp);
}
}
})
</script>
</body>
v-bind
<body>
<!--
v-bind 可以给标签的属性绑定一个data对象中的数据,从而控制标签的属性。
v-bind 可以省略
-->
<div id="app">
<img v-bind:title="imgTitle" src="http://tva2.sinaimg.cn/large/83e2e207jw1fchpgbeyg8j21c00u0dkb.jpg"
class="imgStyle" />
<br>
<!-- <span v-bind:class="{isActive:textL}">一段文本</span> -->
<!-- isActive为真才取textL值 -->
<span v-bind:class="{textL:isActive}" @click="changeClass">一段文本</span>
</div>
<script>
var app = new Vue({
el: "#app",
data: {
imgTitle: "你的名字",
isActive: true
},
methods: {
changeClass: function () {
this.isActive = !this.isActive;
}
}
})
</script>
</body>
v-for
<body>
<!--
1.v-for="item in items" 会遍历整个items,item代表每一个数据遍历项.
v-for="(item,index) in items" item表示每一个数据遍历项,index代表索引值.
2.v-for作用的标签,有几个遍历项,标签就渲染几次.
3.使用{{}}插值语法来取数据.
-->
<div id="app">
<h4>周末做什么:</h4>
<ol>
<li v-for="todo in todos">{{todo}}</li>
</ol>
<h4>无序列表:</h4>
<ul>
<li v-for="(item,index) in users" v-bind:title="item.age">
{{index}} --> {{item.name}}
</li>
</ul>
<button @click="addUser">添加用户</button>
<button @click="minusUser">减少用户</button>
</div>
<script>
var app = new Vue({
el: "#app",
data: {
// 基本数组
todos: [
"吃饭",
"睡觉",
"打游戏",
"看剧"
],
// 对象数组
users: [
{ name: "小明", age: 23 },
{ name: "小花", age: 21 },
{ name: "明华", age: 33 }
]
},
methods:{
addUser(){
this.users.push({name:"某某",age:24})
},
minusUser(){
this.users.shift();
}
}
})
</script>
</body>
v-for中:key的作用原理
v-for="(item,index) in items" :key=index,用遍历的索引值作为key
:key会作为遍历项的一个属性出现,存在于虚拟dom中,真实dom看不见,用index的话,假如你是从数据数组的头加入新数据老刘,就会生成以下新的dom,会拿着key=0去和旧的虚拟dom比对,找到一样的key后,看这个值不一样,就不能复用旧的虚拟dom,就用老刘-30,但是输入框一样,就复用旧的了,张三-18。用index作为key,就会出现这样比对错乱的问题。所以最好用下面数据自身的id作为key标识。
如果不写:key=xxx的话,Vue默认是用遍历的索引index。
v-for="item in items" :key=item.id ,用元素自身的id标识
v-model
<body>
<!--
v-model用于表单元素和vue数据对象的双向绑定
1.v-model只能用于表单元素,常见的表单元素有:input(text,button,radio...),select,checkbox...
v-model双向绑定,vue数据和表单元素数据两者相互影响.
2.v-bind只是单向绑定,vue数据改变才会改变属性数据,属性数据改变不影响vue数据.
-->
<div id="app">
<!-- <span v-model="message"></span> -->
<input type="text" v-model="message" @keyup.enter="showData">
<input type="text" v-bind:value="message" @keyup.enter="showData">
</div>
<script>
var app = new Vue({
el:"#app",
data:{
message:"默认文本"
},
methods: {
showData() {
alert("vue实例中的数据:" + this.message);
},
},
})
</script>
</body>
记事本案例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>记事本</title>
<!-- 引入vue.js,开发环境版本,包含了有帮助的命令行警告 -->
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<style>
.w{
padding-left: 26‒;
margin-left: 38px;
}
</style>
</head>
<body>
<div id="app">
<h2>小菜鸡记事本</h2>
<!-- v-model和输入框的value属性绑定,可以用于获取用户的输入. -->
<input type="text" placeholder="请输入任务" @keyup.enter="addItem()" v-model="inputValue">
<ul>
<li v-for="(item,index) in items" @mouseenter="floatDelete" @mouseleave="hideDelete">
{{index+1+'.'}} {{item}}
<span v-show="isDelete" @click="deleteItem(index)">x</span>
</li>
</ul>
<span v-show="items.length != 0">{{items.length}} items left</span> <span v-show="items.length != 0" class="w" @click="clear">clear</span>
</div>
<script>
var app = new Vue({
el:"#app",
data:{
items:[
"吃饭",
"睡觉",
"打游戏"
],
inputValue:"",
isDelete:false,
total: 3
},
methods:{
addItem(){
console.log("inputValue:"+this.inputValue);
this.items.push(this.inputValue);
this.inputValue = "";
// console.log("inputValue:"+this.inputValue);
},
floatDelete:function(){
this.isDelete = true;
},
hideDelete(){
this.isDelete = false;
},
deleteItem(index){
this.items.splice(index,1);
this.total = this.items.length;
if(this.items.length == 0){
this.isDelete = false;
}
},
clear(){
this.items.splice(0);
}
}
})
</script>
</body>
</html>
axios网络请求库
是一个网络请求库,我的理解就是向后台发送请求,返回自己需要的资源。
1、安装
方式一:使用npm下载axios依赖
npm install axios
方式二:在线导入(要保证联网)
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
2、使用,作一个音乐播放器
两种常用的请求:GET POST
axios.get(地址?参数列表).then(function(response){},function(err){})
请求成功则执行前面的函数 失败执行后面的函数
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>悦听player</title>
<!-- 样式 -->
<link rel="stylesheet" href="./css/index.css">
<!-- 开发环境版本,包含了有帮助的命令行警告 -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<!-- 官网提供的 axios 在线地址 -->
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
</head>
<body>
<div class="wrap">
<!-- 播放器主体区域 -->
<div class="play_wrap" id="player">
<div class="search_bar">
<img src="images/player_title.png" alt="" />
<!-- 搜索歌曲 -->
<input type="text" autocomplete="off" v-model="key" @keyup.enter="search" />
</div>
<div class="center_con">
<!-- 搜索歌曲列表 -->
<div class='song_wrapper'>
<ul class="song_list">
<li v-for="song in songs"><a href="javascript:;" @click="play(song.id,song.al.picUrl)"></a>
<b>{{song.name}}</b>
<span><i v-if="song.mv > 0"><img src="./images/mv.png" @click="playMv(song.mv)"></i></span>
</li>
<!-- <li><a href="javascript:;"></a> <b>你好</b> <span><i></i></span></li> -->
</ul>
<img src="images/line.png" class="switch_btn" alt="">
</div>
<!-- 歌曲信息容器 -->
<div class="player_con" :class="{playing:isPlay}">
<img src="images/player_bar.png" class="play_bar" />
<!-- 黑胶碟片 -->
<img src="images/disc.png" class="disc autoRotate" />
<img v-bind:src="songPicUrl" class="cover autoRotate" />
</div>
<!-- 评论容器 -->
<div class="comment_wrapper">
<h5 class='title'>热门留言</h5>
<div class='comment_list'>
<dl>
<dt><img src="./images/person.png" alt=""></dt>
<dd class="name">盐焗西兰花</dd>
<dd class="detail">
绝对值得一听,吹爆
</dd>
</dl>
</div>
<img src="images/line.png" class="right_line">
</div>
</div>
<div class="audio_con">
<audio ref='audio' @play="doPlay" @pause="pause" v-bind:src="songUrl" controls autoplay loop
class="myaudio"></audio>
</div>
<div class="video_con" v-show="mvUrl != ''">
<video controls="controls" :src="mvUrl"></video>
<div class="mask" @click="closeMv"></div>
</div>
</div>
</div>
<script src="./js/main.js"></script>
</body>
</html>
var app = new Vue({
el:"#player",
data:{
key:"",
songs:[],
songUrl:"",
songPicUrl:"",
isPlay:false,
mvUrl:""
},
methods:{
// 查询歌曲
search(){
var that = this;
axios.get("https://autumnfish.cn/cloudsearch?keywords="+this.key)
.then(function(response){
console.log(response.data.result.songs);
that.songs = response.data.result.songs;
},function(err){})
},
// 获取歌曲播放url
play(id,url){
this.songUrl = "https://music.163.com/song/media/outer/url?id="+id+".mp3";
this.songPicUrl = url;
},
doPlay(){
this.isPlay = true;
},
pause(){
this.isPlay = false;
},
playMv(mvId){
var that = this;
axios.get("https://autumnfish.cn/mv/url?id="+mvId).then(function(response){
console.log(response.data.data.url)
that.mvUrl = response.data.data.url;
})
},
closeMv(){
this.mvUrl = "";
}
}
})
vue数据代理
computed计算属性
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<!-- 引入vue.js,开发环境版本,包含了有帮助的命令行警告 -->
<script src="../js/vue.js"></script>
</head>
<body>
<!--
计算属性computed,可以动态的计算出一个属性供我们使用。
-->
<div id="app">
姓:<input type="text" v-model="firstName"> <br>
名:<input type="text" v-model="lastName"> <br>
全名:<span>{{fullName}}</span><br>
全名:<span>{{fullName}}</span><br>
全名:<span>{{fullName}}</span><br>
</div>
<script>
var vm = new Vue({
el:"#app",
data:{
firstName:"张",
lastName:"三"
},
// 全名我们我通过姓和名计算出来。
computed:{
// fullName是要被计算的属性名。:{}因为要计算,可能比较复杂,所以用一个配置对象
fullName:{
// 所有 getter 和 setter 的 this 自动地绑定为 Vue 实例。但是如果用箭头函数的话,this就不是vue实例了
// get()方法的返回值作为计算属性的值,且值会被缓存起来,计算所依赖的属性值发生变化会重新计算。
// get()方法调用时间:计算属性第一次读取.计算所依赖的属性值发生变化
get(){
console.log("getter");
return this.firstName + "-" + this.lastName;
},
// 当计算属性一被修改就调用,且会接收修改的新值
set(value){
console.log("setter",value.split('-'));
var arr = value.split('-');
this.firstName = arr[0];
this.lastName = arr[1];
}
}
}
})
</script>
</body>
</html>
watch监视属性
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<!-- 引入vue.js,开发环境版本,包含了有帮助的命令行警告 -->
<script src="../js/vue.js"></script>
</head>
<body>
<div id="app">
<h2>今天天气是{{weather}}</h2><br>
<input type="button" value="点我切换天气" @click="change">
<hr>
<h2>深度监视</h2>
<span>a的值:{{numbers.a}}</span> <input type="button" value="a++" @click="numbers.a++"><br>
<span>d的值:{{numbers.c.d}}</span> <input type="button" value="d++" @click="numbers.c.d++">
</div>
<script>
var vm = new Vue({
el: '#app',
data: {
ishtot: true,
numbers:{
a:1,
b:2,
c:{
d:2
}
}
},
methods: {
change() {
this.ishtot = !this.ishtot;
}
},
computed: {
weather: {
get() {
return this.ishtot ? "大太阳" : "多云";
}
}
},
// watch监视属性
watch: {
// ishot要监视的属性
ishtot: {
// 是否初始化时就调用handler方法.true的话,没等监视的属性变化就调用handler
immediate: true,
// handler方法在被监视的属性变化时就会被调用.
handler(old, newValue) {
console.log("ishot改变了", old, newValue);
}
},
'numbers.a':{
handler(){
console.log("numbers中的a属性改变了..")
}
},
// 深度监视
'numbers':{
// 是否深度监视.默认只监视外层属性,想要监视内部属性,要深度监视.
deep:true,
handler(){
console.log("numbers发生改变");
}
}
}
})
// 另一种写法
// vm.$watch("ishtot", {
// // handler方法在被监视的属性变化时就会被调用.
// handler(old, newValue) {
// console.log("另一种写法:ishot改变了", old, newValue);
// }
// })
</script>
</body>
</html>
Vue生命周期
创建之前和创建之后、挂载之前和挂载之后、更新之前和更新之后、销毁之前和销毁之后。
这边的模板指的是我们vue所挂载的节点中的所有元素内容。
<body>
<div id="app">
<h2>n的值: {{n}}</h2>
<button @click="n++">n+1</button>
</div>
<script>
var vm = new Vue({
el:'#app',
data:{
n:1
},
methods:{
}
})
</script>
</body>
这就是模板:
<h2>n的值: {{n}}</h2>
<button @click="n++">n+1</button>
理解:
创建之前和创建之后
挂载之前和挂载之后
更新之前和更新之后
销毁之前和销毁之后
Vue的组件
为什么要学组件?
什么是Vue组件?
组件就是页面中的用于实现局部效果的代码(htm、css、js)和资源(map3、mp4、ttl...)的集合。这个集合构成一个局部效果页面。
组件的好处:提高代码的复用率,哪里有个部分一样,直接引入即可。简化项目编码。
组件的使用
VueComponent
Vue的原型对象(Vue.prototype)上有这些东西,这些东西Vue实例对象vm和组件实例对象vc都可以访问到,当vm.属性/方法名()或vc.属性/方法名()执行的时候,会先在自己身上找这个属性或方法,如果没有,就会顺着线找到Vue的原型对象身上,就是下面这些。
Vue脚手架
使用脚手架创建项目
第一步(仅第一次执行):全局安装@vue/cli。
cmd命令行下输入命令:npm install -g @vue/cli
备注:如出现下载缓慢请配置 npm 淘宝镜像:npm config set registry https://registry.npm.taobao.org
第二步:切换到你要创建项目的目录,然后使用命令创建vue前端项目
vue create xxxx项目名
第三步:启动项目
npm run serve
项目的目录结构
ref属性 与 props配置对象
ref属性
1. 作用:用于给节点打标识,类似节点设置id属性,方便操作dom元素
2. 读取方式:this.$refs.xxxxxx
<template>
<div>
<!-- ref属性用在html标签属性上 -->
<h1 ref="msg">{{msg}}</h1>
<!-- ref属性用在组件标签上 -->
<student ref="stu"></student>
<button @click="showDOM">点我操作dom</button>
</div>
</template>
<script>
import Student from "./components/Student.vue"
export default {
name:"App",
components:{Student},
data() {
return {
msg: "学生",
};
},
methods:{
showDOM(){
// 组件中的this代表组件实例对象VueComponent
console.log(this.$refs.msg);
console.log(this.$refs.stu);
}
}
}
</script>
<style>
</style>
props配置对象
作用:用于父组件给子组件传递数据,数据不再在组件的data中写死,父组件中传什么数据给子组件,子组件就展示什么数据。
背景:
<div>
<!--
当组件的样式啥是固定的,但是里面展示的数据想要动态的传入的话,可以使用props配置对象.
age="23"传的是字符串,要写成 v-bind:age="23" 或 :age="23" 属性绑定,才会传数字,因为23会被当成表达式.
-->
<!-- 付款方 -->
<Student name="张三" sex="男" :age="23"></Student>
<hr>
<Student name="李四" sex="女" :age="26"></Student>
</div>
Vue收集表单数据
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<!-- 引入vue.js,开发环境版本,包含了有帮助的命令行警告 -->
<script src="../js/vue.js"></script>
</head>
<body>
<!--
若:<input type="text"/>,则v-model收集的是value值,用户输入的就是value值。
若:<input type="radio"/>,则v-mode收集的是value值,且要给标签配置value值,因为单选框无法再输入值了。
若:<input type="checkbox"/>
1、没有配置input的value属性,name(v-model)收集的就是checked(勾选 or 未勾选,是布尔值)
2、配置input的value属性:
(1)v-model的初始值是非数组,不是用数组收集,那么收集的就是checked(勾选 or 未勾选,是布尔值)
(2)v-model的初始值是数组,用数组收集,那么收集的就是value组成的数组
备注:v-model的三个修饰符:
(1)lazy:失去焦点在收集数据
(2)number:输入字符串转为有效的数字
<input type="number" 是规定页面输入的时候只能输数字
v-model.number="phone"> 这样vue就能自动将收集到的数字帮我们转为数值型
(3)trim:输入首尾空格过滤
-->
<div id="app">
<form action="" @submit.prevent="finish">
账号: <input type="text" v-model.trim="account"> <br><br>
密码: <input type="password" v-model="password" autocomplete> <br><br>
电话: <input type="number" v-model.number="phone"> <br><br>
性别:
男<input type="radio" name="sex" v-model="sex" value="male">
女<input type="radio" name="sex" v-model="sex" value="female">
<br><br>
爱好:
看电影<input type="checkbox" v-model="hobby" value="film">
打游戏<input type="checkbox" v-model="hobby" value="game">
看妹子<input type="checkbox" v-model="hobby" value="beauty">
<br><br>
所属地区:
<select name="" id="" v-model="area">
<option>请选择地区</option>
<option>莆田</option>
<option>福州</option>
<option>泉州</option>
<option>厦门</option>
</select>
<br><br>
其他信息:
<textarea v-model.lazy="other">
</textarea>
<br><br>
<input type="checkbox" v-model="agree">阅读并接受<a href="http:www.baidu.com">《用户协议》</a>
<button>提交</button>
</form>
</div>
<script>
var vm = new Vue({
el:'#app',
data:{
account:"",
password:"",
other:"",
sex:"female",
// hobby:""
hobby:[],
area:"",
agree:false,
phone:""
},
methods:{
finish(){
console.log(JSON.stringify(this._data));
}
}
})
</script>
</body>
</html>
Todo-list 案例(组件开发流程)
1.实现静态组件:
抽取组件,使用组件实现静态页面效果
拆分组件:可以按功能点拆分(组件是实现界面局部功能点的代码和资源的集合)
Header组件:具有输入任务名,和添加任务的功能。
List组件:具有展示任务的功能
Item组件:具有勾选任务和删除任务的功能
Footer组件:具有展示已完成和全部任务数、还有删除完成的任务等交互功能
注意:当你分的组件,不好起名字时,说明可能你拆分的组件不合适,可以考虑重新拆分。 组件的命名不要和html元素一样。
2.展示动态数据:
2.1. 数据的类型、名称是什么?
类型考虑好,常用的:[{},{},{},{},....]。名称要做到见名知意。
2.2. 数据保存在哪个组件?
若数据只有某个组件自己用的,那么data数据就写在组件自身身上就可以。如果是几个组件一起用,那么将数据放在几个组件共同的父组件身上(方便组件通信用)。
3.交互——从绑定事件监听开始
组件的通信:
父组件==>子组件:父组件给子组件传递数据data、方法method等:可以用props传递。
子组件==>父组件:父组件要先使用props给子组件传递一个方法,然后子组件接收后,调用这个方法给父组件传递数据。
子组件==>子组件:现在只知道可以通过父组件这个中转站实现。
webStorage(
Vue配置代理解决跨域请求
Vue中发送请求的几种方式
这边推荐使用axios,使用命令npm i axios安装一下
什么是跨域请求?
当前发起请求的域 与 所请求的资源 所在的域不一样,就是跨域请求。这里的域指的是这样的一个概念:我们认为如果协议 + 域名 + 端口号均相同,那么就是同域,否则则是跨域的
为了安全起见,浏览器设置了同源策略,当页面执行脚本的时候,浏览器会检查访问的资源是否同源,如果不是,就会报错。
如何解决跨域问题?
1、cors
2、jsonp
3、配置代理服务器(可以使用nginx配置一台代理服务器或使用vue-cli起一台代理服务器)
使用vue-cli配置代理服务器
在Vue.config文件中配置代理,修改完这个文件,记得重启项目才能生效
const { defineConfig } = require('@vue/cli-service')
module.exports = defineConfig({
transpileDependencies: true,
lintOnSave:false, /*关闭语法检查*/
// 配置一个代理服务器(方式一)
/* devServer: {
// 这个配置的是要代理的请求要代发送给谁
// 这种有两个不好的地方:只能配置一台要转发的服务器。如果本服务器上有和代理请求一样的资源名时,就不会走代理了,直接返回本服务器上同名的资源,不能灵活控制是否走代理。
// public目录下就是本服务器上的资源.
proxy: 'http://localhost:5000'
} */
// 配置一个代理服务器(方式二)
devServer: {
proxy: {
// 当资源路径以 /stu 开头时,一定走代理
'/stu': {
// 告诉代理服务器请求发送给谁
target: 'http://localhost:5000',
// 代理请求路径重写,匹配路径http://localhost:8080/stu/students中的/stu改为''
pathRewrite:{'^/stu':''},
// 开启支持websocket
ws: true,
// 是否将请求的host和目标服务器的host保持一致
changeOrigin: true
},
'/car': {
target: 'http://localhost:5001',
pathRewrite:{'^/car':''},
// 以下两个配置在vue中默认是true
// ws: true,
// changeOrigin: true
},
}
}
})
app组件
export default {
name: "App",
methods: {
getStu() {
// 发送请求获取学生信息
axios.get("http://localhost:8080/stu/students").then(
// 请求成功返回给你一个response对象
response => {
console.log("收到学生数据了:",response.data)
},
// 请求失败返回给你一个error对象
error => {
console.log("请求失败:",error.message)
}
)
},
getCars() {
// 请求代理服务器,让他代发请求,解决跨域
axios.get("http://localhost:8080/car/cars").then(
response => {
console.log("收到汽车数据了:",response.data)
},
error => {
console.log("请求失败:",error.message)
}
)
},
},
};
Vuex
专门在 Vue 中实现集中式状态(数据)管理的一个 Vue 插件,对 vue 应 用中多个组件的共享状态(数据)进行集中式的管理(读/写),也是一种组件间通信的方 式,且适用于任意组件间通信。
什么时候用Vuex?
当多个组件共享一个数据时。
如何使用Vuex?
安装vuex3:npm i vuex@3
store是管理Actions、Mutations和State三个的。
Vue中路由
Vue中的路由就是为了实现单页面应用,整个应用只有一个页面index.html,点击页面中的导航不会刷新页面,只会做页面的局部刷新,所需的数据通过Ajax请求回来。
一个路由就是一个请求路径对应一个组件的key-value键值对,key是路径,value是组件。
路由器是管理多个路由的。
当我们点击了学科管理后,地址栏地址变成xxx/subject,然后vue的router就会检测到路径的改变,于是乎去路由规则里面去找有没有对应的组件和/subject对应,如果有的话则展示学科组件。(这个路由规则是我们自己定的)
安装使用
vue2只能安装vue-router3的用,npm i vue-router@3
几个注意点
相关 API:
1. this.$router.push(path): 相当于点击路由链接(可以返回到当前路由界面)
2. this.$router.replace(path): 用新路由替换当前路由(不可以返回到当前路由界面)
3. this.$router.back(): 请求(返回)上一个记录路由
4. this.$router.go(-1): 请求(返回)上一个记录路由
5. this.$router.go(1): 请求下一个记录路由
编程式路由导航
不借助router-link标签实现路由,之前我们一直使用router-link标签实现路由,实质上最后会转为a标签让我们点击实现路由切换。
this.$router.push/replace直接指定要切换哪个路由
pushShow(m){
// push切换路由
this.$router.push({
path:'/home/message/detail',
query:{
id:m.id,
title:m.title
}
})
},
replaceShow(m){
// push切换路由
this.$router.replace({
name:'detail',
query:{
id:m.id,
title:m.title
}
})
}
}
{
// 如果请求路径是/home,则展示Home组件内容
path:'/home',
component:Home,
// 二级路由,/home/xxx,二级路由路径不用加/,因为会自己加
children:[
{
path:'news',
component:News
},
{
path:'message',
component:Message,
children:[
{
name:'detail',
path:'detail',
component:Detail
}
]
},
]
},
缓存路由组件
在要被缓存的组件外加keep-alive标签,属性include指定要缓存的组件名。如果不加include属性的话,只要在这个地方展示过的组件都会被缓存起来。
两个关于路由的生命周期函数
activated(){} 路由切到当前组件且展示当前组件时执行,组件活了
deactivated(){} 路由切到其他组件且展示其他组件时执行,组件失活