Vue学习
基础js代码
<!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>
<h1>0</h1>
<button>按我加一</button>
<button>按我减一</button>
</div>
<script>
var a1 = document.getElementsByTagName("h1")[0];
var b1 = document.getElementsByTagName("button")[0];
var b2 = document.getElementsByTagName("button")[1];
var num = 0
b1.onclick = function () {
num++;
a1.innerHTML=num;
}
b2.onclick=function(){
num--;
a1.innerHTML=num;
}
</script>
</body>
</html>
vue数据驱动试图
核心代码
插值语法:{{}}
内部可以放表达式,表达式支持简单,比如简单判断,比如三元表达式,不可以使用if等复杂判断
{{a>=100?20:10}}
new Vue({
//挂载点
el: '#app',
//数据
data: {
a: 0
},
//方法
methods: {
add() {
this.a++
},
minus() {
this.a--
}
},
})
创建vue文件

访问浏览器,弹出函数,则为引用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>{{ a }}</h1>
<button @click="add">按我加一</button>
<button @click="minus">按我减一</button>
</div>
<script src="js/vue.js"></script>
<script>
new Vue({
//挂载点
el: '#app',
//数据
data: {
a: 0
},
//方法
methods: {
add() {
this.a++
},
minus() {
this.a--
}
},
})
</script>
</body>
</html>
常用指令-v-if和v-show
v-if的作用是通过一个布尔表达式进行对dom的上树和下树的渲染
<div id="app">
<p v-if="true">我是第一行dom元素</p>
<p v-if="false">我是第二行dom元素</p>
</div>

也可以通过带有布尔值的素达式进行判断
<script src="js/vue.js"></script>
<div id="app">
<p v-if="boo">我是第一行dom元素</p>
<p v-if="!boo">我是第二行dom元素</p>
</div>
<script>
var vue = new Vue({
el: '#app',
data: {
boo: false
},
methods: {
}
})
</script>

也可以通过其他方法

或

v-if例子

v-else
需要注意的是v-else的使用前提是必须先有v-if并且中间不允许有任何的元素间隔

注意

v-show
<div id="app">
<p v-show="boo>=5">我是5</p>
<button @click="add">按我加一</button>
</div>
<script src="js/vue.js"></script>
<script>
var vue = new Vue({
el: '#app',
data: {
boo: 5
},
methods: {
add () {
this.boo++
}
}
})
</script>
V-show是通过控制display属性来判断显示和隐藏的


v-show和v-if的使用场景区分是如果页面切换的特别频繁使用v-show,如果页面的涉及范围特别大并日不是特别频繁的切换使用v-if
v-for使用
<li v-for="(item,index)in arr":key="index">{{index}}-{{item]]</li>
item指的是被遍历的数组(对象)的每一个值,item的命名不是规定的,可以自定义命名
index指的是每一项被遍历的值的下标索引值
key是用来给每一项值加元素标识,作用是为了区分元素,为了实现最小量的更新
<body>
<div id="app">
<ul>
<li v-for="(item,index) in arr" :key="">{{index}}-{{item}}</li>
</ul>
</div>
<script src="js/vue.js"></script>
<script>
var vue = new Vue({
el: "#app",
data: {
arr: [
'kobe',
'neymar',
'ronaldo',
'messi'
]
}
})
</script>
</body>

v-for遍历对象
<body>
<div id="app">
<ul>
<li v-for="(item,index) in obj" :key="index">{{index}}:{{item}}</li>
</ul>
</div>
<script src="js/vue.js"></script>
<script>
var vue = new Vue({
el: "#app",
data: {
obj: {
name: 'neymar',
age: '17岁',
sex: '男',
phone: '1341325343'
}
}
})
</script>
</body>
和数组内容不同的是index此时代表的是对象的key

如果用三个参数来表示
<li v-for="(item,key,index) in obj" :key="index">{{index}}-{{key}}:{{item}}</li>
item表示对象的内容,
key表示的是对象key键值名称
index表示的是当前obj的下标索引值
v-for遍历json
<body>
<div id="app">
<table>
<td>name</td>
<td>age</td>
<td>sex</td>
<td>height</td>
<tr v-for="(item,index) in arr">
<!--JSON-->
<td>{{item.name}}</td>
<td>{{item.age}}</td>
<td>{{item.sex}}</td>
<td>{{item.height}}</td>
</tr>
</table>
</div>
<script src="js/vue.js"></script>
<script>
var vue = new Vue({
el: "#app",
data: {
arr: [
{ name: "ming", age: "19", sex: "nan", height: "180" },
{ name: "zhou", age: "15", sex: "nan", height: "176" },
{ name: "hong", age: "16", sex: "nv", height: "160" },
{ name: "ning", age: "17", sex: "nan", height: "167" },
]
}
})

v-for的嵌套
<body>
<div id="app">
<table>
<tr v-for="i in number">
<td v-for="j in number">{{i}}*{{j}}</td>
</tr>
</table>
</div>
<script src="js/vue.js"></script>
<script>
var vue = new Vue({
el: "#app",
data: {
number: [1, 2, 3, 4, 5, 6, 7, 8, 9]
}
})
</script>
</body>

九九乘法表
<body>
<div id="app">
<table>
<tr v-for="i in number" key="i">
<td v-for="j in i" key="j">{{i}}X{{j}}={{i*j}}</td>
</tr>
</table>
</div>
<script src="js/vue.js"></script>
<script>
var vue = new Vue({
el: "#app",
data: {
number: [1, 2, 3, 4, 5, 6, 7, 8, 9]
}
})
</script>
</body>

v-htm指令
v-html和v-text都是渲染文本的指令,使用场景会有不同:
双大括号在渲染结果之前,隐约会有编译之前的文本显示(会显示{{}}),V-text是没有这种现象的
双大括号更灵活,中间是可以添加内容的,V-text是只能渲染data中的数据,中间不允许插入内容
双大括号和v-text它俩的渲染方式和v-html有本质不同,v-html会识别模板
<div id="app">
<p>----------------{{a}}---------------</p>
<p v-text="a">-------------------</p>
<p v-html="a">-----------------</p>
</div>
<script src="js/vue.js"></script>
<script>
var vue = new Vue({
el: "#app",
data: {
a: "<h1>你好啊</h1>"
}
})
</script>
</body>

v-clock
v-cloak指令的作用是vue实例渲染后结束关联
双大括号插值语法在遇到网络延迟的时候会显示编译前的文本

<style>
/*有[V-cloak]选择器的元素进行隐藏*/
[v-cloak] {
display: none;
}
</style>
<body>
<div id="app" v-cloak>
{{a}}
</div>
<script src="js/vue.js"></script>
<script>
var vue = new Vue({
el: "#app",
data: {
a: '我是v-cloak'
}
})
</script>
</body>
display:none,由于v-cloak属性的作用是实例加载后关联结束,所以我们可以实现网络延迟时不显示编译器的文本需要注意的是V-cloak容易写成V-clock
v-once
v-once的作用是只会渲染对应元素一次,数据更新不会引起视图的更新,目的是为了优化页面的性能
<body>
<div id="app" v-cloak>
<h2 v-once>{{a}}</h2>
<button @click="add">加一</button>
<button @click="minus">减一</button>
</div>
<script src="js/vue.js"></script>
<script>
var vue = new Vue({
el: "#app",
data: {
a: 100
},
methods: {
add () {
this.a++;
console.log(this.a)
},
minus () {
this.a--;
console.log(this.a)
}
}
})
</script>
</body>

100指的是初始的元素值,右侧通过点击事件后数据确实发生了变化,但是视图没有改变
使用场景通常是没有动态的元素内容,比如一些文章,一些固定标题
v-pre
v-pre属性的作用是跳过该元素编译过程,直接显示元素内部的文本,特点就是跳过大量的没有指令的节点
<div id="app" v-cloak>
<h2 v-pre>{{a}}</h2>
</div>
<script src="js/vue.js"></script>
<script>
var vue = new Vue({
el: "#app",
data: {
a: 100
}
})
</script>
直接显示
可以直观的看到没有编译之前的效果
v-on
| 事件名称 | 方法 |
|---|---|
| 点击 | onclick |
| 双击 | ondblclick |
| 鼠标移上 | onmouseenter |
| 鼠标离开 | onmouseleave |
| 鼠标滑过 | onmousemove |
| 鼠标移除 | onmouseout |
| 失去焦点 | onblur |
| 聚焦 | onfocus |
| 键盘事件 | onkeydown |
上表的方法都是原生的JavaScript的事件方法,在vue中的使用是一律去除on,然后添加v-on:或者@
<button @click="add">jiayi</button>
<button v-on:click="minus">jianyi</button>
注意点:
原生的JavaScript的事件方法是不能和vue混用的
<button click="add">jiayi</button>错误示范
同名方法会有覆盖情况,后写方法会覆盖先写的方法

可以传入参数
<div id="app">
<h2>{{a}}</h2>
<button @click="add(5)">jiayi</button>
<button v-on:click="minus">jianyi</button>
</div>
<script>
var vue = new Vue({
el: "#app",
data: {
a: 100
},
methods: {
add (num) {
this.a += num
},
minus () {
this.a--
}
}
})
</script>
如果方法中没有传入值,默认输入会有该方法的事件参数
<button v-on:click="minus">jianyi</button>
minus () {
this.a--
console.log(event)}

v-bind
v-bind属性的作用是将普通的w3c属性变为动态属性,让属性具有动态能力
<img src="'images/'+url+'.jpg'">//直接拼参是不可以的

<img v-bind:src="'images/'+url+'.jpg'">//v-bind

v-bind可以简写为冒号:
<img :src="'images/'+url+'.jpg'">//v-bind
实现图片循环
<div id="app">
<div>
<img v-bind:src="'images/'+url+'.png'">
</div>
<button @click="add">jiayi</button>
<button v-on:click="minus">jianyi</button>
</div>
<script>
var vue = new Vue({
el: "#app",
data: {
url: 1
},
methods: {
add () {
this.url++
if (this.url > 3) {
this.url = 1
}
},
minus () {
this.url--
if (this.url < 1) {
this.url = 3
}
}
}
})
</script>
我们可以使用动态属性实现class类名的动态效果
//CSS样式
<style>
p{
width: 200px;
height: 200px;
background: blue;
}
.red{
background:red;
}
.pink{
background: pink;
}
</style>
//结构代码
<div id="app" v-clock>
<div>
<p :class="{red:a >=5,pink: a>=10}">
{{a}}
</p>
</div>
<button @click="add">点击加1</button>
<button @click="minus">点击减1</button>
</div>
<script src = "js/vue.js"></script>
<script>
var vue = new Vue({
el: "#app",
data: {
a: 0
},
methods:{
add(event) {
this.a ++
},
minus(){
this.a --
}
}
})
</script>p :class="{red:a >=5,pink: a>=10}">
{{a}}
</p>
需要注意的是动态的class必须要使用{}去包裹,值可以有多个,值的参数是一个布尔值

除了class属性可以实现动态外,style属性可有对应的功能
style属性和class属性有特殊性,如果需要使用动态传值,必须传入一个object对象
<style>
p {
width: 200px;
height: 200px;
background-color: blue;
}
</style>
<body>
<div id="app">
<div>
<p :style="{width:b+'px'}">
{{b}}
</p>
</div>
<button @click="add">jiayi</button>
<button v-on:click="minus">jianyi</button>
</div>
<script>
var vue = new Vue({
el: "#app",
data: {
b: 200
},
methods: {
add () {
this.b++
},
minus () {
this.b--
}
}
})
</script>

v-model
v-model属性是使用在表单元素中的,作用是实现表单和数据的双向绑定
<p>
姓名:<input type="text" v-model="val">
{{val}}
</p>
<div id="app" v-cloak>
<p>
姓名:<input type="text" v-model="val">
{{val}}
</p>
<script>
var vue = new Vue({
el: "#app",
data: {
val: '姓名是张三'
}
})
</script>
</div>

练习:
<body>
<div id="app" v-cloak>
<h2>问卷调查</h2>
<p>
姓名:<input type="text" v-model="name">
</p>
<p>
性别:
<input type="radio" name="sex" value="男" v-model="sex">男
<input type="radio" name="sex" value="女" v-model="sex">女
</p>
<p>
爱好:
<input type="checkbox" name="hobby" value="打篮球" v-model="hobby">打篮球
<input type="checkbox" name="hobby" value="踢足球" v-model="hobby">踢足球
<input type="checkbox" name="hobby" value="羽毛球" v-model="hobby">羽毛球
</p>
<p>
籍贯:
<select name="native" id="" v-model="native">
<option value="河北">河北</option>
<option value="青岛">青岛</option>
<option value="揭阳">揭阳</option>
<option value="山西">山西</option>
<option value="上海">上海</option>
</select>
</p>
<p>
您填写的表单内容为:姓名:{{name}},性别:{{sex}},爱好:{{hobby}},籍贯:{{native}}
</p>
<button @click="submit">提交</button>
</div>
<script>
var vue = new Vue({
el: "#app",
data: {
name: '',
sex: '男',
hobby: [],
native: '河北'
},
methods: {
submit () {
//汇总信息提交到后端
let obj = {
name: this.name,
sex: this.sex,
hobboy: this.hobby,
native: this.native
}
console.log(obj)
}
}
})
</script>
</body>

案例--选项卡
<!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>
<style>
* {
margin: 0;
padding: 0;
}
.box {
width: 302px;
margin: 100px auto;
border: 1px solid #ddd;
}
.box .header {
height: 35px;
line-height: 35px;
}
.box .header span {
float: left;
width: 100px;
border-right: 1px solid #fff;
background: #ddd;
text-align: center;
color: #fff;
cursor: pointer;
}
.box .header span:last-child {
border-right: none;
}
.box .header .cur {
background: #fff;
color: #ddd;
}
.box .content {
line-height: 30px;
font-size: 14px;
padding: 5px;
}
.box .content p {
border-bottom: 1px solid #ddd;
}
</style>
<body>
<div class="box" id="app">
<div class="header">
<span :class="{cur: curState==index}" v-for="(item,index) in hTitle"
@mouseenter="displayState(index)">{{item}}</span>
</div>
<div class="content" v-show="curState==0">
<p>首页</p>
<p>首页</p>
<p>首页</p>
<p>首页</p>
<p>首页</p>
<p>首页</p>
</div>
<div class="content" v-show="curState==1">
<p>娱乐</p>
<p>娱乐</p>
<p>娱乐</p>
<p>娱乐</p>
<p>娱乐</p>
<p>娱乐</p>
</div>
<div class="content" v-show="curState==2">
<p>新闻</p>
<p>新闻</p>
<p>新闻</p>
<p>新闻</p>
<p>新闻</p>
<p>新闻</p>
</div>
</div>
<script src="js/vue.js"></script>
<script>
var vue = new Vue({
el: "#app",
data: {
hTitle: ['首页', '娱乐', '新闻'],
showContent: true,
curState: 0
},
methods: {
displayState (index) {
this.curState = index;
}
}
})
</script>
</body>
</html>

案例--调色板
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
p.pickers{
width: 200px;
height: 200px;
background: blue;
}
</style>
</head>
<body>
<div id="app" v-clock>
<p class="pickers" :style="{background:'rgb('+r+','+g+','+b+')'}"></p>
<p>
r:<input max="255" min="0" type="range" v-model="r"/><input max="255" min="0" v-model="r" type="number">
</p>
<p>
g:<input max="255" min="0" type="range" v-model="g"/><input max="255" min="0" v-model="g" type="number">
</p>
<p>
b:<input max="255" min="0" type="range" v-model="b"/><input max="255" min="0" v-model="b" type="number">
</p>
</div>
<script src = "js/vue.js"></script>
<script>
var vue = new Vue({
el: "#app",
data: {
r: 100,
g: 200,
b: 123
},
methods:{
}
})
</script>
</body>
</html>

案例--微博发布框
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.warn{
color:red;
}
</style>
</head>
<body>
<div id="app">
<textarea v-model='content' cols="30" rows="10" placeholder="请发表你今天的心情。。。。"></textarea>
<!-- warn生效机制:当内容的数量大于100的时候,渲染文字为红色 -->
<p :class="{warn: content.length > 100}">{{content.length}}/100</p>
<p>
<!-- disabled生效机制:当内容的数量大于100的时候,不能点击 -->
<button :disabled="content.length > 100">发布</button>
<!-- disabled生效机制:当内容的小于等于0的时候,不能点击 -->
<button @click="clear" :disabled="content.length <= 0">清空</button>
</p>
</div>
<script src='js/vue.js'></script>
<script>
var vue = new Vue({
el:'#app',
data:{
content:""
},
methods:{
// 清空textarea文本输入框的内容
clear() {
this.content = ''
}
}
})
</script>
</body>
</html>

事件修饰符
<div class="outer" @click="outer">
<div class="center" @click="center">
<div class="inner" @click="inner"></div>
</div>
</div>

此时如果点击了inner,其实就相当于点击了center和outer,此时如果都绑定了事件监听,就势必都会被触发

我们现在想阻止这种事件冒泡,通过两种方法:
1 1stop修饰符(常用)
<div class="outer" @click="outer">
<div class="center" @click="center">
<div class="inner" @click.stop="inner"></div>
</div>
</div>

通过上面的案例,我们了解了.stop修饰符的作用就是阻止事件的一个冒泡
其作用类似原生JavaScript的event.stopPropagation()方法
inner(event) {
event.stopPropagation();
console.log("内层")
}
2.self修饰符
.self修饰符的作用是只有点击元素本身的时候才能触发事件,不接受冒泡上来的事件,同时也不能阻止事件的冒泡
<div class="outer" @click.self="outer">
<div class="center" @click.self="center">
<div class="inner" @click.self="inner"></div>
</div>
</div>
需要三个都加上self,每个层级的 @click.self 都是为了确保点击事件不会向上传播。
如果
<div class="outer" @click="outer">
<div class="center" @click.self="center">
<div class="inner" @click.self="inner"></div>
</div>
</div>

3.prevent修饰符
如果一个超级链接,既有链接,又有事件,此时点击超级链接后会先执行事件的内容,然后会执行a默认的跳转事件
此时我们不需要a标签跳转到百度,执行完事件监听后就停止,通过.prevent修饰符阻止
<a href="http://www.baidu.com" @click.prevent="alertDialog">点击跳转到百度</a>
和stop修饰符一样,prevent也有原生的事件方法
4.capture修饰符
capture修饰符是对事件捕获的监听,vue的事件监听,默认都是获取冒泡阶段的,所以使用capture去监听捕获阶段的事件(与冒泡相反方向【从外到内】)
<div class="outer" @click.capture="outer">
<div class="center" @click.capture="center">
<div class="inner" @click="inner"></div>
</div>
</div>
当点击inner时(捕获)

如果不加上capture,点击inner时(冒泡)
<div class="outer" @click="outer">
<div class="center" @click="center">
<div class="inner" @click="inner">
</div>
</div>
</div>

5.once修饰符
once修饰符的作用就是使事件只触发一次
<button @click.once="add">按我加1</button>
methods:{
add(event) {
this.a++
console.log(this.a)
}
}

按键修饰符
JavaScript的onkeydown和onokeyup,这两个是键盘的事件监听,在vue中有对应的事件修饰符
<input type="text" @keyup.space='add'>
.space是vue封装的对keyCode别名,和下面的代码表示内容相同
<input type="text" @keyup.32='add'>
常用的keyCode别名
| keyCode值 | 别名 | 键盘按键 |
|---|---|---|
| 13 | .enter | 回车 |
| 32 | .space | 空格 |
| 37 | .left | 键盘左键 |
| 38 | .up | 键盘上键 |
| 39 | .right | 键盘右键 |
| 40 | .down | 键盘下键 |
| 9 | .tab | 键盘tab |
| 46或者8 | .delete | delete或者backspace |
系统修饰符
系统修饰符指的是通过一些指定的按键配合鼠标点击或者键盘事件进行事件监听
比如.ctrl系统修饰符的使用
<button @click.ctrl='add'>按我加1 </button>此时按住键盘ctrl键然后鼠标点击才能实现add加1
| 修饰符名称 | 对应的键盘键名称 |
|---|---|
| .ctrl | ctrl |
| .alt | alt |
| .shfit | shfit |
| .alt | 如果是windows系统代表的是键盘的徽标键,如果是IOS系统,单表的是common键 |
此时有一个问题,如果我们设置了系统修饰符,并不希望有其他的按键组合,比如我们设置ctrl修饰符,此时如果按住ctrl和其他键,然后再点击鼠标,此时也会触发事件监听,所以我需要使用其他的修饰符来设置精确匹配事件
exact修饰符
<button @click.ctrl.exact='add'>按我加1 </button>
鼠标按键修饰符
鼠标按键修饰符修饰的是鼠标的左、滚轮、右键
<button @click.left='add'>按我加1 </button>
<button @click.middle='add'>按我加1 </button>
<button @click.right='add'>按我加1 </button>
此时我们发现右键点击按钮的时候确实可以实现点击,但是也会出现右键的默认弹窗

<button @click.right.prevent='add'>按我加1 </button>
prevent修饰符实现右键的事件监听
表单修饰符
表单修饰符一共有三个,分别是.lazy,.number,.trim
表单修饰符都是用来修饰v-model属性的.
.lazy修饰符是将Input输入框的数据绑定v-model从实时监听的状态变为change状态
<div id="app">
<input type="text" v-model.lazy='a'>
<p>{{a}}</p>
</div>

当鼠标的光标失去焦点之后

.number修饰符的作用是将内容转化为数字类型
需要注意的是.number修饰符会将非数字内容进行过滤,得到的是纯数字类型,是可以进行计算的非NaN数字
<input type="text" v-model.number='a' @input='add'>

如果没有使用number修饰符,得到的输入框的数字都是string类型
.trim修饰符的作用是过滤用户输入的收尾空格
比如我们没有设置trim之前

此时我们给v-model修饰trim
<input type="text" v-model.trim='a' @input='add'>

得到的是纯没有收尾空白的内容
<!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">
<div>{{a}}</div>
<input type="text" v-model.lazy='a'>
<div>{{b}}</div>
<input type="text" v-model.number='b'>
<div>{{c}}</div>
<input type="text" v-model.trim='c'>
</div>
<script src="../js/vue.js"></script>
<script>
var vue = new Vue({
el: "#app",
data: { a: 100, b: 200, c: 300 },
methods: {
}
})
</script>
</body>
</html>
创建vue-cli
如何安装cli?
npm install -g @vue/cli
如何查看是否安装成功
npm install -g @vue/cli
管理员打开cmd,进入目的目录,
vue create my-project


vscode打开即可

cli目录结构

node_modules项目的依赖中心
public:静态资源文件夹,和assets不同的是public不会被webpack进行打包,使用路径的时候要使用绝对路径
src:项目的核心区域,所有的开发文件的核心内容区域,包括组件,静态资源等等
asstet:静态资源文件夹,和public不同的是assets文件夹会被webpack打包,所以要使用相对路径
components:Vue功能组件的存放位置,内部存放的是公用的组件
views:公共文件,主要以各个独立页面为主
APP.vue:整个vue的根组件,所有的vue组件都是从这个组件中拓展的,App根组件最后通过编译后将内容渲染到.html文件中
main.js:vue的入口文件,vue文件初始化位置
.gitignore:GitHub相关配置文件,作用是git再提交代码的时候指定相关忽略格式文件
babel.config.js:babel的配置文件
package.json:配置(记录了)项目的相关模块,项目相关配置信息等等
package-lock.json:作用是记录的当前项目安装的相关依赖版本,并且记住了当前所有依赖的关联关系,如果下次vue进行编译的时候会按照这个文件进行编译
README.md:文件的作用是项目相关的使用方法,和使用说明
cli文件的编译过程
npm run serve
第一步命令会找到node_modules文件夹中.bin文件夹内部的vue-cli-service文件

然后我们根据路径查找到了相关文件

核心代码路径

severice.js文件是整个编译过程的核心文件

App.vue文件
App.vue文件是整个项目的根组件,项目中所有的页面切换页面显示都是在这个组件基础上渲染的
我们将整个App.vue文件清空后发现
<template>
<div id="app">
</div>
</template>
<script>
export default {
components: {
}
}
</script>
<style>
上面的结构是.vue文件的基础结构
<template>元素的作用是搭建vue文件的结构
<script>元素的作用是对当前文件逻辑进行交互
<style>元素的作用是对当前文件的样式进行修饰
js文件只有逻辑.css文件只有样式.html文件只有结构,但是.vue的组建就是将视图和逻辑进行了一个整合
组件
所有的vue组件都是以.vue格式结尾的文件
我们看到的vue-cli中的App.vue文件就是整个vue的根组件
<template>
<div>
</div>
</template>
<script>
export default {
data(){
}
}
</script>
<style>
一个vue文件就是一个类
需要注意的地方是data必须是一个函数
最外层必须有默认暴露
<script>
export default {
data(){
return {
}
}
}
</script>
我们后面写的所有的vue的对象清单都必须在export default里面去罗列
在我们之前写data时候是一个对象
var app = new Vue{
data: {
name:'小明'
}
}
data是一个函数,返回的是一个对象,目的是为了让每个组件数据隔离,这个是JavaScript的原理,并不是vue去设计的
如何定义组件
比如在components文件夹中创建一个NeymarPlayer.vue文件
App.vue文件
<template>
<img alt="Vue logo" src="./assets/logo.png">
<NeymarPlayer ></NeymarPlayer>
</template>
<script>
// 引入组件
import NeymarPlayer from './components/NeymarPlayer.vue'
export default {
// 注册组件
name: 'App',
components: {
NeymarPlayer
}
}
</script>
总结使用组件三步走:
1)创建vue文件
2)在要渲染的地方引入该组件
3)注册该组件
组件内容
<template>
<div>
{{ a }}
<button @click="add" >dasdsa</button>
</div>
</template>
<script>
export default {
data() {
return {
a: 111
}
},methods:{
add(){
this.a++
}
}
}
</script>
<style lang="scss" scoped>
</style>

组件是可以复用的,并且数据是隔离的
在给App.vue多添加几个NeymarPlayer.vue文件
<template>
<NeymarPlayer ></NeymarPlayer>
<NeymarPlayer ></NeymarPlayer>
<NeymarPlayer ></NeymarPlayer>
</template>

父子组件传值
我们使用组件一定是依托在某一个父组件的身上,比如我们上面写的Mashibing.vue文件就是依托在App.vue文件中,此时我们如果要使用App.vue文件中的值怎么办
vue提供了一个props的入口,也是父子组件之间唯一的传值方式,父组件通过v-bind自定义属性传入值,子组件通过props接受对应的参数
父组件
<template>
<div>
<Mashibing :msb-value="a"></Mashibing>
</div>
</template>
公共v-bind自定义属性传值,注意由于vue的属性对大小写不敏感,所以如果需要写驼峰命名,需要使用-隔开,比如msb-value代表的就是msbValue
data(){
return {
a: 100
}
}
代码:
<template>
<div>
<NeymarPlayer :msb-value="b"></NeymarPlayer>
</div>
</template>
<script>
import NeymarPlayer from './components/NeymarPlayer.vue'
export default {
components: {
NeymarPlayer
},
data(){
return {
b: 1200
}
}
}
</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>
子组件
<template>
<div>
<h1>马士兵教育,我接收到的父组件的值是:{{msbValue}}</h1>
<h1>{{c}}</h1>
<button @click="add"> add</button>
</div>
</template>
<script>
export default {
// 罗列父组件传进的属性值
props:['msbValue'],
data() {
return {
c: 12200
}
},
methods:{
add() {
this.c ++
}
}
}
</script>
<style lang="scss" scoped>
</style>
在父组件中,你将 msb-value 绑定到 a,也就是说你传递的是父组件的数据 a 的值 1200。因此,当你在子组件中访问这个 prop 时,它的值就是 1200。
子组件的 msbValue 直接来自父组件的 a,而不是子组件内部的 c。如果你希望在子组件中显示 12200,你需要直接在子组件中使用 this.c,而不是 prop。或者,你可以通过修改父组件的 a 来让它传递不同的值。
效果:

子组件通过props罗列父组件的传值,接收的参数可以有多个,props可是数组,也可以是对象
<div>
<Mashibing :msb-value="a" :value-b="b" :value-c="c"></Mashibing>
</div>
<template>
<div>
<h1>马士兵教育,我接收到的父组件的值是:{{msbValue}} {{valueB}}
{{valueC}}</h1>
</div>
</template>
<script>
export default {
// 罗列父组件传进的属性值
props:['msbValue','valueB','valueC'],
data() {
return {
a: 100
}
},
methods:{
add() {
this.a ++
}
}
}
</script>

可以使用对象去接收参数
props:{
msbValue: Number,
valueB: Number,
valueC: Number
}
如果props是一个对象,那么这个对象的key是自定义传入参数属性,value是希望传入的参数类型
比如我们限制的是数字类型
但是我们传入的是一个字符串,此时,控制台后报错,提示你希望传入number类型

如果props是对象的话,参数可以配置,比如配置参数必填项:
props:{
msbValue: {
type: Number,
required: true
},
valueB: Number,
valueC: Number
},
如果props的值也是一个对象,type代表的是类型,required是一个布尔值,如果为ture代表的是设置必填项,如果不填,则会抛出错误

比如default代表的是默认的不传入的值的参数
msbValue: {
type: Number,
default: 500
}

如果props的default值是Object或者Array,需要使用函数return
msbValue: {
type: Object,
default: ()=>{
return {a:100}
}
}

validator是数据的校验
msbValue: {
type: Number,
// 数据的校验
validator: function(value) {
return value > 101
}
}

子组件修改父组件的参数
子组件不可以直接修改父组件的值,只能传出一个自定义事件,父组件通过调用这个自定义事件后,然后在外部修改值
子组件代码
<template>
<div>
<h1>马士兵教育,我接收到的父组件的值是:{{msbValue}}</h1>
<h1>{{c}}</h1>
<button @click="add"> add</button>
</div>
</template>
<script>
export default {
// 罗列父组件传进的属性值
props:['msbValue'],
data() {
return {
c: 12200
}
},
methods:{
add() {
this.$emit("add")
}
}
}
</script>
<style lang="scss" scoped>
</style>
$emit方法是vue封装的,用来想父组件返回对应的自定义事件,父组件通过在子组件身上设置对应的自定义事件后设置事件名称
父组件代码:
<template>
<div>
<NeymarPlayer @add="sumNum" :msb-value="b"></NeymarPlayer>
</div>
</template>
<script>
import NeymarPlayer from './components/NeymarPlayer.vue'
export default {
components: {
NeymarPlayer
},
data(){
return {
b: 1200
}
},
methods:{
sumNum(){
this.b++
}
}
}
</script>

@add自定义事件是子组件通过$emit传出来的自定义事件,父组件通过这个事件设置事件方法sunNum,然后修改自己的值,从而时间子组件修改父组件的值

24.cnblogs.com/blog/3463783/202501/3463783-20250120150112106-1600715605.png)

浙公网安备 33010602011771号