一、介绍
Vue是一套渐进式框架,用来动态构建用户界面(view)。
二、基本认识
1. MVVM模式
M:model,数据对象(data中的数据)
V:view,模板页面(页面中所显示的内容),是动态的html页面
VM:VueModel,new 的Vue对象,也就是vm对象
三、创建实例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<input type="text" v-model="uaddr">
<p>{{uaddr}}</p>
<p v-text="url"></p>
<p v-html="url"></p>
<!-- <img :src="vueimg">-->
<button v-on:click="test1">按钮1完整写法</button>
<button @click="test1">按钮2无参数</button>
<button @click="test2('abc')">按钮3带参数abc</button>
</div>
<script src="../res/vue.js"></script>
<script>
new Vue({
el:"#app",
data:{
uaddr: "hxxy",
url: "<a href='https://www.baidu.com/'>百度</a>",
vueimg: "https://cn.vuejs.org/images/logo.svg",
},
methods:{
test1(){
alert("vue 点击事件");
},
test2(param){
alert("vue 点击事件-->"+param);
},
}
})
</script>
</body>
</html>
1.双大括号显示数据
<p>{{msg}}</p><!-- textContent 整个内容-->
2.强制数据绑定
<img v-bind:src='vueimg' alt=""> <!-- 完整写法 -->
<img :src='vueimg' alt=""> <!-- 简洁写法 -->
3.绑定事件
<button v-on:click="test1">按钮1完整写法</button>
<button @click="test1">按钮2无参数</button>
<button @click="test2('abc')">按钮3带参数abc</button>
四、计算属性
1.简述
模板页面(view)适用于简单的声明式逻辑
计算属性是vm实例对象中的另一个配置对象,适用于复杂逻辑
computed函数在初始化时调用,相关属性变化时也触发
1.1 默认计算属性
当计算属性中只有一个回调函数时,此回调函数默认是getter,可显示当前属性数据
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="comp">
fris: <input type="text" v-model="fris"><br>
second: <input type="text" v-model="second"><br>
name(singel): <input type="text" v-model="name1"><br>
name(tow): <input type="text" v-model="name2">
</div>
<script src="../res/vue.js"></script>
<script>
new Vue({
el:"#comp",
data:{
fris: "1",
second: "2"
},
computed:{
// 此回调函数什么时候执行:1.初始化显示时执行,2.相关属性数据发生变化时
// 用来干什么:计算并返回当前属性的值
//计算属性中的一个方法,方法的返回值为属性值,回调函数
name1(){
return this.fris+' '+this.second;
},
name2:{
get(){
//回调函数,计算并返回当前属性的值
// 回调函数的特点:1.你定义的,2.你没有调用,3.但最终执行了
// 回调函数用来干嘛的?什么时候被调用?
// 执行:当需要读取当前属性值的时候回调,用处:根据相关的数据计算并返回当前属性的值
return this.fris+' '+this.second
},
set(value){
// 回调函数,监视当前属性值的变化,当属性值发生改变时回调,更新相关的属性数据
//value就是name2的最新属性值
// value.split()方法使用指定的分隔符字符串将一个value对象分割成子字符串数组
const name=value.split(' ');//以空格分开
this.fris=name[0];
this.second=name[1];
}
}
},
})
</script>
</body>
</html>
五、强制绑定Class和Style
语法 :class=‘xxx’,:style=’{color:activeColor,fontSize+“px”}’
其中activeColor/fontSize是data属性
xxx可以是字符串、对象、数组
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<style>
.aClass{
font-size: 30px;
}
.bClass{
color: cornflowerblue;
}
.cClass{
color: chocolate;
}
</style>
<body>
<div id="demo">
<p class="cClass" :class="a">xxx是字符串</p>
<!-- <p :class="{aClass:false,bClass:true}">xxx是对象</p>这样跟下面在data对象里设置isA的值为true是一样的 -->
<p :class="{aClass:isA,bClass:isB}">xxx是对象</p><!-- 用的多 -->
<p :class="['aClass','bClass']">xxx是数组</p>
<p :style="{color:activeColor,fontSize:fontSize+'px'}">hello world</p>
<button @click="update">按钮</button>
</div>
<script src="../res/vue.js"></script>
<script>
new Vue({
el:"#demo",
data:{
a: 'cClass',
isA: true,
isB: false,
activeColor: 'red',
fontSize: 5
},
methods:{
update(){
this.a = 'bClass';
this.isA = false;
this.isB = true;
this.activeColor = 'blue';
this.fontSize = 30
}
}
})
</script>
</body>
</html>
六、条件渲染
1.简述
v-if 如果if中条件为真,则以此处内容渲染页面
v-else 如果if中条件为假,则以此处内容渲染页面
v-show 如果此处属性值为真,则以此处内容渲染页面,如果属性为假,则隐藏
2.区别
v-if 隐藏时,是将标签移除,切换消耗高。在运行时如果条件很少改变,则用v-if
v-show 不移除,而是通过改变元素的css属性display来实现显示与隐藏。如果需要频繁切换,则用v-show
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<!--
1.条件渲染指令
v-if
v-else
v-show
2.比较v-if 与v-show
如果需要频繁切换v-show 较好
v-show效率高
-->
<body>
<div id="demo">
<p v-if="ok">测试v-if成功</p>
<p v-else>测试v-if失败</p>
<p v-show="ok">测试v-show成功</p>
<p v-show="!ok">测试v-show失败</p>
<button @click="ok=!ok">切换</button>
</div>
<script src="../res/vue.js"></script>
<script>
new Vue({
el: "#demo",
data: {
ok: true
},
})
</script>
</body>
</html>
七、列表渲染
1.v-for使用
v-for 可遍历数组、对象,并利用 key 管理可复用的元素
<body>
<div id="demo">
<p>v-for数组</p>
<ul>
<li v-for="(p,index) in persons" :key="index">
{{index}}---{{p.name}}----{{p.age}}
<button @click="deleteP(index)">删除</button>---
<button @click="updated(index,{name:'newOne',age:21})">更新</button>
</li>
</ul>
<p>v-for对象</p>
<ul>
<li v-for="(value,key) in persons[1]" :key="value">
{{key}}---- {{value}}
</li>
</ul>
</div>
<script src="../res/vue.js"></script>
<script>
new Vue({
el: "#demo",
data: {
persons: [
{name: 'ack',age: 19},
{name: 'jack',age: 17},
{name: 'eack',age: 18},
{name: 'gack',age: 16}
]
},
methods:{
deleteP(index){
this.persons.splice(index,1);
},
updated(index,newP){
this.persons.splice(index,1,newP)
}
}
})
</script>
</body>
key值
因为 Vue 会尽可能高效地渲染元素,所以通常会复用已有元素而非从头开始渲染。 如果没有在两个可切换的输入框中分别加上唯一的key值,切换后,输入框中被输入的内容不会清除,会被复用 如果添加了key值,则向系统说明“这两个元素是独立的,不要复用他们”
2.列表的搜索和排序
2.1解构赋值
解构赋值 - JavaScript | MDN (mozilla.org)
2.2假设有一个对象数组,我们想要根据某个对象属性对数组进行排序。而传递给数组sort()方法的比较函数要接收2个参数,即要比较的值。 可是,我们需要一种方式指明按照哪个属性来排序。 要解决这个问题,可以定义一个函数,它接收一个属性名,然后根据这个属性名来创建一个比较函数。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="demo">
<input type="text" v-model="searchName">
<ul>
<li v-for="(p,index) in filterPersons" :key="">
{{p.name}}==={{p.age}}
</li>
</ul>
<button @click="setOrder(1)">升序</button>
<button @click="setOrder(2)">降序</button>
<button @click="setOrder(0)">原序</button>
</div>
<script src="../res/vue.js"></script>
<script>
new Vue({
el: "#demo",
data: {
searchName: '',
orderType: 0,//0原序,1升序,2降序
persons: [
{name: 'ack',age: 19},
{name: 'jack',age: 17},
{name: 'eack',age: 18},
{name: 'gack',age: 16}
]
},
methods:{
setOrder(value){
this.orderType=value;
}
},
computed:{
filterPersons(){
//获取相关参数
const {searchName,persons,orderType}=this; //采用解构赋值
//过滤person
let filterPersons;
filterPersons=persons.filter(p => p.name.indexOf(searchName)>=0);//这里》=0表示能找到得到下标
//排序
if (orderType!==0){
filterPersons.sort(function (p1,p2){
if (orderType===1){
return p1.age-p2.age;
}else {
return p2.age-p1.age;
}
})
}
return filterPersons;
}
}
})
</script>
</body>
</html>
八、事件处理
1.v-on:xxx=‘fn’
@xxx = ‘fn’
@xxxx = ‘fn(参数)’ , 默认事件形参:event (绑定监听时可不传参数event),隐含属性对象: $event
2.1 @xxx.stop
停止事件冒泡,相当于 event.stopPropagation()
2.2 @xxx.prevent
阻止事件的默认行为(a标签的自动跳转页面),相当于 event.preventDefault()
2.3 @xxx.passive
立即出发事件的默认行为,例如 scroll 滚动事件,提升移动端的性能
2.4 @xxx.once
点击事件只会触发一次
2.5 @keyup.enter
按下回车触发
2.6 注意
在事件处理程序中调用 event.preventDefault() 等方法在js中很常见
但在 Vue 中要尽可能地只调用方法,代码只处理纯粹的数据逻辑,不处理 dom 事件
所以尽量少用事件修饰符来处理 dom 事件
<body>
<div id="demo">
<div style="width: 300px;height: 300px;background-color: chocolate" @click="test1">
<div style="width: 100px;height: 100px;background-color: cornflowerblue" @click.stop="test2"></div>
</div>
<a href="https://fanyi.baidu.com/#en/zh/split" @click.prevent="test3">百度翻译</a>
<input type="text" @keyup.enter="test4">
</div>
<script src="../res/vue.js"></script>
<script>
new Vue({
el: "#demo",
methods: {
test1() {
alert("out")
},
test2() {
alert("inner")
},
test3() {
alert("你点击了百度翻译")
},
test4(event){
alert(event.target.value)
}
},
})
</script>
</body>
九、表单输入绑定
v-model (双向数据绑定)自动收集数据,收集完之后就可使用ajax发送给后台
1.checkbox:
多选,收集到的数据为数组,data初始化数据时也要将其定义为数组,再为其写唯一的 value 值
2. radio:
单选,为每个选项写唯一的 value 值,后台收集的数据即 value 值
3. select:
下拉框,收集到的数据为数组,里面的元素为对象,包含标识符 id 和 name ,后台收集的数据为 id 值
三者设置value后加上v-model,在data中的初始值会使得它默认选中。
<body>
<div id="demo">
<form action="" @subimt.prevent="handelSubmit" method="get">
<span>用户名:</span>
<input type="text" v-model="username"><br>
<span>性别:</span>
<input type="radio" id="female" value="女" v-model="sex">
<label for="female">女</label>
<input type="radio" id="male" value="男" v-model="sex">
<label for="male">男</label><br>
<span>爱好:</span>
<input type="checkbox" id="baskBall" value="baskBall" v-model="likes">
<label for="baskBall">篮球</label>
<input type="checkbox" id="foot" value="foot" v-model="likes">
<label for="foot">足球</label>
<input type="checkbox" id="mao" value="mao" v-model="likes">
<label for="mao">羽毛球</label><br>
<span>城市:</span>
<select v-model="cityId">
<option value="">未选择</option>
<option :value="city.id" v-for="(city,key) in allCitys" :key="key">{{city.name}}</option>
</select>
<input type="submit" value="提交">
</form>
</div>
<script src="../res/vue.js"></script>
<script>
new Vue({
el: "#demo",
data: {
username: '',
sex: '男',
likes: [],
allCitys: [{id:1,name:'BJ'},{id:2,name:'SH'},{id:3,name:'GZ'}],
cityId: '',
},
})
</script>
</body>
十、VUE对象的 生命周期
1.初始化
beforeCreate()
created()
beforeMount()
mounted()
2.更新显示
beforeUpdate()
updated()
3.销毁
beforeDestory()
destoryed()
十一、属性监视
深度监视:
(1)Vue中的watch默认不监测对象内部值的改变(一层)。
(2)配置deep : true可以监测对象内部值改变(多层)。
备注:
(1)Vue自身可以监测对象内部值的改变,但Vue提供的watch默认不可以!
(2) 使用watch时根据数据的具体结构,决定是否采用深度监视。
示例:
<body>
<div id="vue1">
<h1>欢迎来到{{name}}学习</h1>
<button @click="numbers.a++">点击改变a的值</button>
<p>a的值是:{{numbers.a}}</p><br><br>
<button @click="numbers.b++">点击改变b的值</button>
<p>b的值是:{{numbers.b}}</p>
</div>
</body>
<script src="./res/vue.js"></script>
<script>
new Vue({
el:'#vue1',
data:{
name:'家里蹲',
numbers:{
a:1,
b:1,
}
},
methods:{
},
watch:{
numbers:{
deep:true,
handler(){
console.log("number 改变")
}
}
}
})
</script>
Vue的set()方法:该方法能直接向Vue实例的data中的对象或集合添加额外的属性以及值
Vue.set(target,'k','v')
实例:
<button @click="addNum">点击添加学号</button>
...
addNum(){
Vue.set(this.school,'num','20')
}
十二自定义指令、
自定义指令可以实现自身的需求:定义v-xxx(多单词组成的时候可以用下划线拼接)
用 - 拼接时,directives里的名字用 ‘ ’ (单引号)括起来。
自定义的指令函数参数1是调用该指令的html标签对象,参数2是对应的值
该指令何时被调用?
1.指令与元素成功绑定时(一上来);2.指令所在的模板被重新解析的时候
自定义组件总结:
1.定义语法
(1)局部指令:
new Vue({
directives:{
指令名:配置对象
或
指令名:配置函数
}
})
(2)全局指令:
Vue.direcitve(指令名,配置对象)或(指令名,函数)
2.配置对象中常用的3个回调:
(1)bind
(2)inserted
(3)update
示例:
<body>
<div id="vue1">
<h1>欢迎来到{{name}}学习</h1>
<p>n的值是:{{n}}</p>
<p>放大十倍是:<span v-big="n"></span></p><br>
<button @click="n++">点击n+1</button>
//需求:定义一个input标签,获取num值并且页面加载完成后聚焦。
<input type="text" v-fbind="n">
</div>
</body>
<script src="./res/vue.js"></script>
<script>
//定义全局的指令函数
//Vue.directive('指令名称',具体函数/对象);
new Vue({
el:'#vue1',
data:{
name:'家里蹲',
n:1,
},
methods:{
},
directives:{
//自定义的指令函数参数1是调用该指令的html标签对象,参数2是对应的值
//该指令何时被调用? 1.指令与元素成功绑定时(一上来);2.指令所在的模板被重新解析的时候
big(element,binding){
console.log("big 指令调用");
element.innerText=binding.value*10;
},
fbind:{
//页面指令与元素成功绑定时
bind(element,binding){
element.value=binding.value;
},
//元素被插入页面时
inserted(element,binding){
element.focus();
},
update(element,binding){
element.value=binding.value;
}
}
}
})
</script>
十三、组件化
几个注意点:
1.关于组件名:
一个单词组成:
第一种写法(首字母小写): school
第二种写法(首字母大写): School
多个单词组成:
第种写法(kebab-case命 名):my- school
第三种写法(CamelCase命名): MySchool ( 需要Vue脚手架支持)
备注:
(1)组件名尽可能回避HTML中已有的元素名称,例如: h2、 H2都不行。
(2)可以使用name配置项指定组件在开发者工具中呈现的名字。
2.关于组件标签:
第一种写法: <school></ school>
第二种写法: <schoo1/>
备注:不用使用脚手架时,<school/> 会导致后续组件不能渲染。
3.一个简写方式:
const school = Vue. extend( options)可简写为: const school = options
-->
组建的嵌套示例:
<script>
Vue.config.productionTip=false;
//定义stu组件
const stu=Vue.extend({
template:'<div><div>学生:{{name}}</div><div>学号:{{num}}</div></div>',
data(){
return{
name:'wmr',
num:20,
}
}
})
//定义school组件
const school=Vue.extend({
template:"<div><div>这个是{{sch}}学生信息:</div><stu></stu><div>{{sch}}宣。。。</div></div>",
components:{
stu
},
data(){
return{
sch:'家里蹲'
}
}
})
//定义school同级组件top
const tops=Vue.extend({
template:'<h1>欢迎来到{{name}}学习</h1>',
data(){
return{
name:'家里蹲'
}
}
})
//定义一个一人之下万人之上的跟元素
const app=Vue.extend({
template:'<div><p>{{info}}</p><tops></tops><school></school></div>',
components:{
school,
tops
},
data(){
return{
info:'组件的嵌套'
}
}
})
new Vue({
template:'<app></app>',
el:'#vue1',
components:{
app
}
})
</script>
VueComponent构造函数:
关于VueComponent:
1. schoo1组件本质是一个名为VueComponent的构造函数, 且不是程序员定义的,是Vue. extend生成的。
2.我们只需要写<school/>或<school></school>, Vue解析时会帮我们]创建school组件的实例对象,
即Vue帮我们执行的: new VueComponent (options)。
3.特别注意:每次调用Vue.extend,返回的都是一个全新的VueComponent!!!!
4.关于this指向:
(1) 组件配置中:
data函数、methods 中的函数、watch中的函数、computed中 的函数它们的this均是[VueComponent实例对象]
(2) new Vue()配置中:
data函数、methods中的函数、watch中的函数、computed中的函数它们的this均是[Vue实例对象]。
5. VueComponent的实例对象,以后简称vc ( 也可称之为:组件实例对象)。
Vue的实例对象,以后简称vm。
重要的内置关系
有点类似于java的继承关系。
ref属性:
1.被用来给元素或子组件注册引用信息(id的替代者)
2.应用在html标签上获取的是真实DOM元素,应用在组件标签上是组件实例对象(vc )
3.使用方式:
打标识: <h1 ref="xxx">.....</h1> 或<School ref=" xxx">< /School>
获取: this . $refs . xxx
props属性:
功能:让组件接收外部传过来的数据
(1)传递数据:
<Demo name= ”xxx" >
(2)接收数据:
第一种方式(只接收) :
props:[ ' name ']
第二种方式(限制类型) :
props:{
name : Number
}
第三种方式(限制类型、限制必要性、指定默认值) :
props:{
name :{
type:String, //类型
required:true, //必要性
default:'老王' //默认值
备注: props 是只读的,Vue 底层会监测你对props的修改,如果进行了修改,就会发出警告,
若业务需求确实需要修改,那么请复制props的内容到data中一份, 然后去修改data中
的数据。
mixin混入:
功能:可以把多个组件共用的配置提取成个混入对象
使用方式:
第1步定义混合。例如:
export const commonCode1={
methods:{
addMyage(){
this.myAge++;
}
}
}
第2步使用混入, 例如:
//局部混入
<script>
import {commonCode1} from '../common'
export default {
.
.
.
mixins:[commonCode1]
}
</script>
App文件中配置全局的mixins
import {commonCode1,commonCode2} form '路径'
Vue.mixin(commonCode1)
Vue.mixin(commonCode2)
Vue中自定义插件的使用:
功能:用于增强Vue
本质:包含install方法的一个 对象,install的第一个参数是Vue,第二个以后的参数是插件使用者传递的数
据。
定义插件:
export default{
install(vue){
console.log(vue)
//全局过滤器
Vue.filter('filterName',function(value){
...
})
//全局指令
Vue.directive('指令名称',具体函数/对象);
//全局混入
Vue.mixin({
...
})
//给Vue原型上添加方法,vm和vc都能用
Vue.prototype.hello = () => {alert('hello world')}
}
}
在App中使用插件
import plugins from '路径'
Vue.use(plugins)
coped样式
作用:让样式在局部生效,防止冲突。
写法: <style scoped>
WebStorage
1.存储内容大小一般支持5MB左右(不同浏览器可能还不一样)
2.浏览器端通过Window.sessionStorage和Window.localStorage属性来实现本地存储机制。
3.相关API:
1. xxxxStorage. setItem('key', 'value');
该方法接受一个键和值作为参数,会把键值对添加到存储中,如果键名存在,则更新其对应的值。
2. xxxxxStorage . getItem(' key' );
该方法接受一个键名作为参数,返回键名对应的值。
3. xxxxxStorage . removeItem('key' );
该方法接受一个键名作为参数,并把该键名从存储中删除。
4. xxxxxStorage . clear()
该方法会清空存储中的所有数据。
4.备注:
1. SessionStorage存储的内容会随着浏览器窗口关闭而消失。
2. LocalStorage存储的内容,需要手动清除才会消失。
3. xxxxStorage. getItem(xxx)如果xxx对应的value获取不到,那么gettem的返回值是null.
4. JSON. parse(null)的结果依然是null。