第十四章 VUE
- 首先安装node.js,之后在cmd窗口运行npm -v查看是否完成
- 在资源管理器中找到想要加载vue的目录,之后使用cmd命令看看是不在本目录下
- 执行 npm install vue@2.6.10,等待下载完成
- 下载完成之后会在本目录下边生成一个node_module目录和package-lock.json
- 如果下载失败可以使用 npm set registry https://registry.npm.taobao.org/
1.VUE输出数据
- 大胡子表达式
一般书写在正文中
{{ 要输出的初始化的值}}
<p>{{ XXX }}</p>
- 使用VUE的指令元素
<!--v-指令名 指令功能强大,大部分书写在标签中,不需要进行dom操作
想要对那个元素添加元素动作样式就在这个节点上书写,不需要对这些元素进行操作了-->
<p v-指令名-XXX></p>
2.VUE指令元素
<script>
let vm = new Vue({
el : '#app',
data:{
k1:v1,
k2:v2
}
})
</script>
- 一次性插值 v-once
<h3>1.v-once一次性插值</h3>
<span v-once> {{ msg }}</span>
//以下的值都是书写在data里边的 无法更改
msg : '一锤子买卖'
- 插入结构样式 v-html
此指令不能用来插入js代码,可以插入html,css
<h3>2:v-html插入结构样式</h3>
<div v-html="hyper" style="background-color: pink;"></div>
hyper:'<a href="#" style="text-decoration: none;color: blue;">我是添加进来的文本</a>'
- 绑定元素属性 v-bind
完全写法
v-bind:style=“mystyle”
简略写法:(语法糖)使用较多
:style=“mystyle”
<h3>3:v-bind绑定元素属性</h3>
<img v-bind:src="mysrc" :style="mystyle" :title="mytitle" >
- 绑定元素动作(语法糖@)
v-on:
<h3>4:v-on绑定元素动作(语法糖@)</h3>
<button @click=touch>点我试试</button>
<input type="text" v-model="count" :style="mycss">
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>2指令元素</title>
</head>
<body>
<div id="app">
<h3>1:v-once一次性插值</h3>
<span v-once>{{ msg }}</span>
<h3>2:v-html插入结构样式</h3>
<div v-html="hyper" style="background-color: pink;"></div>
<h3>3:v-bind绑定元素属性</h3>
<img v-bind:src="mysrc" :style="mystyle" :title="mytitle" >
<h3>4:v-on绑定元素动作(语法糖@)</h3>
<button @click=touch>点我试试</button>
<input type="text" v-model="count" :style="mycss">
</div>
<script src="./node_modules/vue/dist/vue.js"></script>
<script >
let vm = new Vue({
el : '#app',
data:{
msg:'我就是一锤子买卖',
hyper:'<a href="#" style="text-decoration: none;color: blue;">我是添加进来的文本</a>',
mysrc:'image/logo.png',
mystyle:'width:80px',
mytitle:'渐进式框架',
count:100,
mycss:'background-color:rgb(255,0,255)'
},
methods: {
touch(){
console.log('我被点击了')
//通过this.data中的属性名可以更改data中的值
this.count++
let r = Math.floor(Math.random()*255)
let g = Math.floor(Math.random()*255)
let b = Math.floor(Math.random()*255)
this.mycss = `background-color:rgb(${r},${g},${b})`
}
},
})
</script>
</body>
</html>
3.计算属性和函数
- 绑定函数(单向绑定)
注意使用v-model绑定函数时,应该添加括号,不管是否传值,绑定函数一律写在methods中
绑定函数
函数仅仅支持单项绑定,也就是更改data中的值可以修改函数的返回值
但是不支持双向绑定,无法直接修改返回值从而更改data中的值
没有缓存机制,不管是否参数发生改变每次都会执行
在控制台直接输入 vm.sumScore(),虽然参数没有发生变化,但是依然执行
数学成绩: <input type="text" v-model="mathScore">
<br>
英语成绩: <input type="text" v-model="englishScore">
<br>
<!-- 注意使用v-model绑定函数时,应该添加括号,不管是否传值 -->
总成绩(绑定函数-单向绑定): <input type="text" v-model="sumScore()">
<script src="./node_modules/vue/dist/vue.js"></script>
<script>
let vm = new Vue({
el:'#app',
data:{
mathScore:60,
englishScore:140,
totalWatch:300
},
methods: {
sumScore(){
console.log('sumScore()激发啦~~~~~')
/*
将数学成绩与英语成绩相加
注意:由于拿取的值有可能是字符串,所以首先要转换为number
最简单的转换方式,String-0 = number
*/
return (this.mathScore-0)+(this.englishScore-0)
}
},
- 设计计算属性
计算属性默认为单向绑定,提供get和set方法之后可以变成双向绑定
计算属性都书写在computed中
注意计算属性默认也仅仅只有单项绑定功能,计算属性存在缓存机制,
如果参数没有发生改变,则自动读取缓存,不再执行
从控制台 输入 vm.totalScore 则不再执行,直接读取缓存
单向绑定的计算属性Es6新特性使用钩子函数,直接带括号,双向绑定的计算属性后边为 : {}
单向:totalScore(){}
双向:totalScores:{}
总成绩(绑定计算属性-默认单向绑定):<input type="text" v-model="totalScore">
<br>
总成绩(绑定计算属性-双向绑定):<input type="text" v-model="totalScores">
computed: {
/*
2:设置计算属性
注意计算属性默认也仅仅只有单项绑定功能,计算属性存在缓存机制,
如果参数没有发生改变,则自动读取缓存,不再执行
从控制台 输入 vm.totalScore 则不再执行,直接读取缓存
*/
totalScore(){
console.log('totalScore激发啦~~~~~')
return (this.mathScore-0)+(this.englishScore-0)
},
/*
3:设置计算属性支持双向绑定
*/
totalScores:{
/* 此函数默认为单项绑定,如果我们不设置双向绑定,则默认就是get函数 */
get(){
console.log('totalScores单向绑定激发啦~~~~~')
return (this.mathScore - 0) + (this.englishScore - 0)
},
/* 此函数为双向绑定,这里的形参就是在总成绩中书写的值 */
set(newValue){
console.log('totalScores双向绑定激发啦~~~~~');
let avgScore = newValue/2
this.mathScore = avgScore
this.englishScore = avgScore
}
}
},
- 局部监听器
局部监听器书写在watch中,监听器需要有一个初始化的值
设置局部监听器,这个监听器放置在Vue实例中,只能在初始化dom节点中使用
成绩(使用监听器-只能监听某个参数的改动): <input type="text" v-model="totalWatch">
<script>
let vm = new Vue({
el : '#app',
data:{
totalWatch:0,
},
watch:{
/*
此处给mathScore绑定监听器,当数学成绩发生变化时,重新计算总成绩 newValue:表示新的数学成绩 oldValue:表示默认的数学成绩
*/
mathScore(newValue,oldValue){
console.log('局部监听器触发啦~~~~');
this.totalWatch = (this.englishScore-0)+(newValue-0)
}
}
})
</script>
- 全局变量
设置全局监听器,全局监听器放置在Vue实例以外,通过对象调用
Vue实例.$watch(监听的参数,function(被监听的参数更改之后的值){
修改监听的参数之后执行的回调函数
}
let vm = new Vue({})
vm.$watch('englishScore',function(newValue){
this.totalWatch = (newValue-0)+(this.mathScore-0)
})
Vue绑定函数 计算属性 监听器 有什么不同?
1)绑定函数
仅有单项绑定功能,不管默认的参数是否发生改变,由于没有缓存机制,都要重新调用
2)计算属性
默认由单项绑定功能,实现get set函数后可以实现双向绑定功能,存在缓存机制,如果默认的参数
没有变化,则不会再次调用
3)监听器
用来监听某个值,这个值必须存在一个默认值,当这个默认值发生改动之后执行,书写在Vue实例内部的是局部监听器
放置在Vue外部为全局监听器
4.设计css⚠️
以下的data都是Vue实例中的data,简写省篇幅
- 设置class属性为初始化的值
这里绑定的是一个字符串,字符串对应的是data中的初始化的值
:class=“data中的值”
<h3>方式1)设置class属性为初始化的值</h3>
<p :class="activeClass">我是一个段落</p>
data:{
activeClass:'red'
}
<style>
.red{background-color:red;}
</style>
- 设置class后面为一个对象
:class=“{类名:data1,类名2:data2}”
data1和data2都是data中初始化的值,如果true则类别生效,为false则类别失效
<style>
.fontColor{
background-color:red;
}
.line{
text-decoration: underline;
}
</style>
<h3>方式2)设置class后面为一个对象</h3>
<p :class="{fontColor:isColor,line:isLine}">我也是一个段落</p>
data:{
isColor:true,
isLine:true
}
- 设置class后边是一个数组
:class=“[类名1,类名2]”
这里直接就是类名,不需要在data中初始化
<p>方式三:设置class后边是一个数组</p>
<p :class="['color','italic']">我还是一个段落</p>
- 绑定行内式
:style="{样式名:data中初始化的样式值,样式名2:data中初始化的样式值2}, 注意这里的样式名必须书写js的书写方式,遵循驼峰格式,不能存在
background-color ===> backgroundColor
<p :style="{backgroundColor:data1,fontSize:data2+'px'}">我是最后也是一个段落</p>
5.条件渲染
- v-if
<h3>1:条件渲染v-if</h3>
<!--
复选框中,如果勾选,则v-model中的值为true,不勾选为false
-->
隐藏元素:<input type="checkbox" v-model="showBox">
<br>
<!--
v-if:条件渲染
如果v-if后面的值为0或者false,则元素隐藏,在dom结构中也不存在
如果不为0或者为true,则元素显示,在dom中存在相应结构,
这种显示隐藏切换开销较大,不适于频繁切换的场合
-->
<div class="box1" v-if="!showBox"></div>
<!-- vue2.5新特性,配合v-if,如果v-if无法显示则运行v-else,两个元素必须紧邻,不能配合v-show使用 -->
<span v-else>div被隐藏啦</span>
<hr>
- v-show
<h3>2:条件渲染v-show</h3>
隐藏元素:<input type="checkbox" v-model="showBox2">
<br>
<!--
v-show:条件渲染
如果v-show后面的值为0或者false,则元素隐藏,注意dom结构在源码中存在
只不过添加了一个display:none
如果后面的值不为0或者true,则元素显示,dom结构中的display:none不存在了
初始载入消耗较大,适合频繁切换的场合
##Vue当中几种条件渲染的不同
-->
<div class="box1" v-show="!showBox2"></div>
6.迭代
- 也可以使用of
每个对象的别名,索引值 后边的key为了解决一个bug
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>6迭代</title>
</head>
<body>
<div id="app">
<ul>
<li v-for="(per,index) in ar" :key="index">
索引值:{{ index }},ID{{ per.id }} , 姓名{{ per.username}},密码:{{ per.password }},
性别:{{ per.gender == '0' ? '女' : '男'}},年领{{ per.age }}
</li>
</ul>
</div>
<script src="./node_modules/vue/dist/vue.js"></script>
<script>
const ar = [
{id:1,username:'elena',password:'12345',gender:'0',age:23},
{id:2,username:'peny',password:'22345',gender:'1',age:28},
{id:3,username:'tom',password:'13345',gender:'1',age:25},
{id:4,username:'jerry',password:'12545',gender:'0',age:13},
{id:5,username:'ammy',password:'12445',gender:'0',age:43}
]
ar.push({id:6,username:'boinne',password:'6666',gender:'0',age:22})
let vm = new Vue({
el : '#app',
//ES6新特性当属性名和属性值恰巧重名时可以省略属性值,指数写属性名
data:{
ar
}
})
</script>
</body>
</html>
数组
7.激发事件
函数无参数则不添加括号,底层自从传输事件原型$event
函数如果传参则添加括号,如果依然需要事件原型,则必须手动传输
$event:是实参,不能随意书写
<button @click="say2('测试2',$event)">点击我说{{ msg }}</button>
事件修饰符针对元素绑定事件时对动作进行补充设置
@事件.事件修饰符=“函数”
stop:表示阻止事件冒泡传递
<button @click.stop="doThis">事件冒泡</button>
prevent:此修饰符可以屏蔽元素固有的属性,例如 链接的提交目的地 如href 表单的action
<a href="./1_MVVM思想.html" @click.prevent="link">我也是一个链接</a>
8.表单
9.自定义指令
10.过滤器
v-model不能搭配过滤器
1.全局过滤器
设置全局过滤器屏蔽敏感词等
Vue.filter('contentFilter1',function(value){
//如果用户没填写任何内容
if(!value){
return ''
}
return value.toString().trim().replace('测试1','测试2').replace('剑道','武术')
})
new Vue({
el:'#app',
data:{
content:'2020中华民国剑道选手权比赛因疫情推迟'
},
2.局部过滤器
filters:{
/*
过滤器名(过滤的值){
}
*/
contentFilter2(value){
if(!value){
return ''
}
return value.toString().trim().replace('测试1','测试2')
.replace('剑道','武术')
}
11实战 todomvc
12.组件
组件componet是vue中最强的之一
Vue中的组件化开发就是把网页的重复代码抽取出来,组成一个可服用的视图组件,然后将这些视图
注意⚠️
1.组件名必须使用横线分割或者驼峰书写方式
例如component-a也可以更改为componentA,官方推荐全部小写,使用-连接
- 模板中书写的内容如果存在单引号双引号等容易引起其一的,建议使用反引号` 就像是模板字符串的写法
- 在页面引用组件时,必须使用横线风格福命名方法,不能使用驼峰
13.单页面组件极致化
14.组件间的通讯
组件通讯存在以下三种方式
- props:父组件向子组件传递数据
- $emit:自定义事件
- slot 插槽分发内容
组件间的通讯规则
- 不能再子组件中直接修改父组件传过来的数据
- 初始化数据时,应该首先看这个初始化的数据是否被应用在多个组建中,如果这个组件应用在多个组件中,则应该在父组件中初始化,如果指在一个组件中使用,就初始化在这个组件中
- 数据初始化在哪个组件,则更新数据的方法或函数应该定义在哪个组件
15 生命周期
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>15Vue生命周期</title>
</head>
<body>
<div id="app">
<h3>{{ msg }}</h3>
</div>
<script src="./node_modules/vue/dist/vue.js"></script>
<script>
const vm = new Vue({
//没有el挂载dom节点,则可以通过$mount来进行手动挂载dom节点
//el:'#app',
data:{
msg:'爱你3000遍'
},
//不加载模板,也不加载数据,无模板无数据
/*
this.$el:表示加载Vue实例管理的模板
this.$data:表示获取所有Vue实例中初始化的data值
*/
beforeCreate() {
console.log('beforeCreate()',this.$el,this.$data);
},
//不加载模板,但是已经加载数据,无模板有数据,这也是最早挂载数据的方法
//由于此函数是第一次获得数据的地点,所以一般发送异步请求,全部书写在此函数中
created() {
console.log('created()', this.$el, this.$data);
},
//有模板有数据,但是数据并没有加载到已经挂载模板上
beforeMount() {
console.log('beforeMount()', this.$el, this.$data);
},
//有模板有数据,数据已经加载到挂载的模板上
mounted() {
console.log('mounted()', this.$el, this.$data);
},
//当加载数据发生更改时,去更新挂载模板之前调用
beforeUpdate() {
console.log('beforeUpdate()', this.$el.innerHTML, this.$data);
},
//当加载数据发生更改时,去更新挂载模板之后调用
updated() {
console.log('updated()', this.$el.innerHTML, this.$data);
},
//需要手动执行 vm.$destroy()来销毁实例
//实例开始销毁,Vue实例完全销毁之前调用
beforeDestroy() {
console.log('beforeDestroy()');
},
//实例销毁结束调用
destroyed() {
console.log('destroyed()');
},
//由于没有el,则可以进行手动挂载
}).$mount('#app')
</script>
</body>
</html>