vue非常详细基基基基基础
1、el挂载点和data
el选项命中的元素及其内部的后代元素,可以使用其他的选择器,但是建议使用id选择器
data中可以写复杂类型的数据,渲染复杂类型数据时,遵守js的语法就可以
<body><div id="app">{{message}}<span>{{message}}</span></div><div class="app2">{{message}}</div><script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script><script>var app=new Vue({el:"#app",//挂载点el用于指定当前Vue实例为哪个容器服务,值通常为css选择器字符串。data:{message:"hello vue"//data中用于存储数据,数据供el所指定的容器去使用,值我们暂时先写成一个对象。}});var app2=new Vue({el:".app2",data:{message:"hello vue2"}})</script>
</body>
<body><div id="app">{{message}}<h2>{{stus.name[1]}}</h2><h3>{{stus.name[2]}}</h3></div><script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script><script>var app=new Vue({el:"#app",data:{message:"hello data",stus:{name:["mike","amy","jack"],num:111111111},city:["guangzhou","beijing","shanghai"]}})</script>
</body>
1.2 容器和实例是一对一的
创建vue实例接管容器
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Document</title>
</head>
<body><div id="app">{{message}} {{message2}}</div><script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script><script>new Vue({el:"#app",//挂载点data:{message:"hello vue"}});new Vue({el:"#app",//挂载点data:{message2:"hello vue222"}});</script>
</body>
</html>
容器和实例是一一对应的
初识Vue:
1.想让Vue工作,就必须创建一个Vue实例,且要传入一个配置对象;
2.root容器里的代码依然符合html规范,只不过混入了一些特殊的Vue语法;
3.root容器里的代码被称为【Vue模板】;
4.Vue实例和容器是一一对应的;
5.真实开发中只有一个Vue实例,并且会配合着组件一起使用;
6.{{xxx}}中的xxx要写js表达式,且xxx可以自动读取到data中的所有属性;
7.一旦data中的数据发生改变,那么页面中用到该数据的地方也会自动更新;
注意区分:js表达式 和 js代码(语句)
1.表达式:一个表达式会产生一个值,可以放在任何一个需要值的地方:
(1). a
(2). a+b
(3). demo(1)
(4). x === y ? ‘a’ : ‘b’
2.js代码(语句)
(1). if(){}
(2). for(){}
<!DOCTYPE html>
<html><head><meta charset="UTF-8" /><title>初识Vue</title><!-- 引入Vue --><script type="text/javascript" src="../js/vue.js"></script></head><body><div id="demo"><h1>Hello,{{name.toUpperCase()}},{{address}}</h1></div><script type="text/javascript" >Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。//创建Vue实例new Vue({el:'#demo', //el用于指定当前Vue实例为哪个容器服务,值通常为css选择器字符串。data:{ //data中用于存储数据,数据供el所指定的容器去使用,值我们暂时先写成一个对象。name:'atguigu',address:'北京'}})</script></body>
</html>
1.3 模板语法
Vue模板语法有2大类:
1. 插值语法:
功能:用于解析标签体内容。
写法:{{xxx}},xxx是js表达式,且可以直接读取到data中的所有属性。
2. 指令语法:
功能:用于解析标签(包括:标签属性、标签体内容、绑定事件…)。
举例:v-bind:href=“xxx” 或 简写为 :href=“xxx”,xxx同样要写js表达式,且可以直接读取到data中的所有属性。把xxx当js表达式执行
备注:Vue中有很多的指令,且形式都是:v-???
<!DOCTYPE html>
<html><head><meta charset="UTF-8" /><title>模板语法</title><!-- 引入Vue --><script type="text/javascript" src="../js/vue.js"></script></head><body><div id="root"><h1>插值语法</h1><h3>你好,{{name}}</h3><hr/><h1>指令语法</h1><a v-bind:href="school.url.toUpperCase()" x="hello">点我去{{school.name}}学习1</a><a :href="school.url" x="hello">点我去{{school.name}}学习2</a></div></body><script type="text/javascript">Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。new Vue({el:'#root',data:{name:'jack',school:{name:'',url:'http://www.baidu.com',}}})</script>
</html>
而x还是固定写死的值
1.4 单向数据绑定
- 语法:
v-bind:href ="xxx" 或简写为 :href
把"xxx"当表达式在data中读取href
特点:数据只能从 data 流向页
<!-- 普通写法 -->
<input type="text" v-bind:value="name"><br/>
<!-- 简写 -->
单向数据绑定:<input type="text" :value="name"><br/>
1.5 双向数据绑定
- 语法:
v-mode:value="xxx" 或简写为 v-model="xxx"
- 特点:数据不仅能从 data 流向页面,还能从页面流向 data
<!-- 普通写法 -->
<input type="text" v-model:value="name"><br/> -->
<!-- 简写 -->
双向数据绑定:<input type="text" v-model="name"><br/>
<!DOCTYPE html>
<html><head><meta charset="UTF-8" /><title>数据绑定</title><!-- 引入Vue --><script type="text/javascript" src="../js/vue.js"></script></head><body><div id="root"></div></body><script type="text/javascript">Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。new Vue({el:'#root',data:{name:'Jack'}})</script>
</html>
第二行改变会影响第一行,因为是双向绑定,但是第一行修改不会影响第二行
如下代码是错误的,因为v-model只能应用在表单类元素(输入类元素)上
<h2 v-model:x="name">你好啊</h2>
1.6 el与data的两种写法
- el有2种写法
(1).new Vue时候配置el属性。
(2).先创建Vue实例,随后再通过vm.$mount(’#root’)指定el的值。mount意思有挂载
//第一种写法
new Vue({el:'#root',
data:{name:'Jack'}
})
//第二种写法 */
const v = new Vue({data:{name:'Jack'}
})v.$mount('#root')
- data有2种写法
(1).对象式
(2).函数式
如何选择:目前哪种写法都可以,以后学习到组件时,data必须使用函数式,否则会报错。 - 一个重要的原则:
由Vue管理的函数,一定不要写箭头函数,一旦写了箭头函数,this就不再是Vue实例了。而是指向window
new Vue({el:'#root',//data的第一种写法:对象式data:{name:'Jack'} })
new Vue({el:'#root',//data的第二种写法:函数式data:function(){console.log('@@@',this) //此处的this是Vue实例对象return{name:'Jack'}}})
<!DOCTYPE html>
<html><head><meta charset="UTF-8" /><title>el与data的两种写法</title><!-- 引入Vue --><script type="text/javascript" src="../js/vue.js"></script></head><body><div id="root"><h1>你好,{{name}}</h1></div></body><script type="text/javascript">new Vue({el:'#root',data:function(){console.log('@@@',this) return{name:'Z'}}})</script>
</html>
data函数不能写成箭头函数
1.7 MVVM
vue参考了MVVM
MVVM模型
- M:模型(Model) :data中的数据
- V:视图(View) :模板代码
- VM:视图模型(ViewModel):Vue实例
观察发现:
- data中所有的属性,最后都出现在了vm身上。
- vm身上所有的属性 及 Vue原型上所有属性,在Vue模板中都可以直接使用。
<!DOCTYPE html>
<html><head><meta charset="UTF-8" /><title>理解MVVM</title><!-- 引入Vue --><script type="text/javascript" src="../js/vue.js"></script></head><body><div id="root"><h1>学校名称:{{name}}</h1><h1>学校地址:{{address}}</h1><!-- <h1>测试一下1:{{1+1}}</h1><h1>测试一下2:{{$options}}</h1><h1>测试一下3:{{$emit}}</h1><h1>测试一下4:{{_c}}</h1> --></div></body><script type="text/javascript">const vm = new Vue({el:'#root',data:{name:'北大',address:'北京',}})console.log(vm)</script>
</html>
vm身上有adress和name
1.8 数据代理
1.8.1 Object.defineproperty
Object.defineProperty()
方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象。
- 语法
Object.defineProperty(obj, prop, descriptor)
参数
obj 要定义属性的对象。
prop 要定义或修改的属性的名称或 Symbol 。
descriptor 要定义或修改的属性描述符。- enumerable:true, //控制属性是否可以枚举,默认值是false
- writable:true, //控制属性是否可以被修改,默认值是false
- configurable:true //控制属性是否可以被删除,默认值是false
返回值 被传递给函数的对象。
<!DOCTYPE html>
<html><head><meta charset="UTF-8" /><title>回顾Object.defineproperty方法</title></head><body><script type="text/javascript" >let number = 18let person = {name:'张三',sex:'男',}Object.defineProperty(person,'age',{// value:18,// enumerable:true, // writable:true, // configurable:true //当有人读取person的age属性时,get函数(getter)就会被调用,且返回值就是age的值get(){console.log('有人读取age属性了')return number},//当有人修改person的age属性时,set函数(setter)就会被调用,且会收到修改的具体值set(value){console.log('有人修改了age属性,且值是',value)number = value}})console.log(Object.keys(person))console.log(person)</script></body>
</html>
<!DOCTYPE html>
<html><head><meta charset="UTF-8" /><title>回顾Object.defineproperty方法</title></head><body><script type="text/javascript" >let number = 18let person = {name:'张三',sex:'男',age:18}console.log(Object.keys(person));for(key in person){console.log(person[key]);}console.log(person)</script></body>
</html>
默认不可迭代,不可修改,不可删除
1.8.1 数据代理
数据代理:通过一个对象代理对另一个对象中属性的操作(读/写)
<!DOCTYPE html>
<html><head><meta charset="UTF-8" /><title>何为数据代理</title></head><body><script type="text/javascript" >let obj = {x:100}let obj2 = {y:200}Object.defineProperty(obj2,'x',{get(){return obj.x},set(value){obj.x = value}})</script></body>
</html>
1.8.3 vue中数据代理
- 1.Vue中的数据代理:
通过vm来代理data对象中属性的操作(读/写) - 2.Vue中数据代理的好处:
更加方便的操作data中的数据 ,不然要写成_data.name
- 3.基本原理:
通过Object.defineProperty()
把data对象中所有属性添加到vm上。
为每一个添加到vm上的属性,都指定一个getter/setter
。
在getter/setter
内部去操作(读/写)data中对应的属性。
<!DOCTYPE html>
<html><head><meta charset="UTF-8" /><title>Vue中的数据代理</title><!-- 引入Vue --><script type="text/javascript" src="../js/vue.js"></script></head><body><div id="root"><h2>名称:{{name}}</h2><h2>地址:{{address}}</h2></div></body><script type="text/javascript">Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。const vm = new Vue({el:'#root',data:{name:'school',address:'广州'}})console.log(vm);</script>
</html>
2、内置指令
2.1、v-text
设置标签的文本值
3. 若使用v-text
指令,将会把标签内的文字全部替换
4. 或者用差值表达式进行部分替换
5. 在v-text
指令内进行字符串拼接,内部支持写表达式
<body><div id="app"><h2 v-text="message">1111111</h2><h2 v-text="name">11111111</h2><h2>{{message}}11111111</h2><!--只有这个的111才显示--><h2 v-text="message+'11111111'"></h2></div><script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script><script>var app=new Vue({el:"#app",data:{message:"v-text",name:"mike"}})</script>
</body>
2.3、v-html
设置标签的innerHTML
v-html
指令作用式设置元素的innerHTML
,内容中有html结构会被解析成标签v-text
指令不论是什么内容,只会解析成文本- 解析文本用
v-text
,解析html结构使用v-html
<body><div id="app"><p v-html="baidu"></p><p v-text="baidu"></p></div><script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script><script>var app=new Vue({el:"#app",data:{baidu:"<a href='https://www.baidu.com/'>百度<a>"}})</script>
</body>
2. 4、v-on
为元素绑定事件
- 绑定的方法定义在
methods
属性中,最终会在vm上; - 方法内部通过
this
关键字可以访问修改定义在data中的数据 - 使用v-on:xxx 或 @xxx 绑定事件,其中xxx是事件名;
- methods中配置的函数,不要用箭头函数!否则this就不是vm了;
- methods中配置的函数,都是被Vue所管理的函数,this的指向是vm 或 组件实例对象;
- @click=“demo” 和 @click=“demo($event)” 效果一致,但后者可以传参;
<body><div id="app"><button v-on:click="sayHi">按钮</button><button @click="sayHi">按钮</button><button @dblclick="addReally">really</button><p> {{feeling}}</p></div><script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script><script>var app=new Vue({el:"#app",data:{feeling:"happy"},methods:{addReally:function(){this.feeling+="really!"},sayHi:function(){alert("你好呀");}}})</script>
</body>
2. 4.1 传递参数
- 事件绑定的方法写成函数调用的形式,可以自定义传入参数
- 定义方法时需要定义形参来接受传入的实参
- 事件后面跟上
.修饰符
可以对事件进行修饰,eg:.enter
可以限制触发的按键为回车键 - 事件修饰符有多种
<div id="app">
<input type="button" @click="doit(p1,p2)"/>
<input type="text" @keyup.enter="sayHi">
</div>
<script>var app=new Vue({el:"#app",methods:{doit:function(p1,p2){},sayHi:function(){}}})
</script>
2. 4.2 事件修饰符
Vue中的事件修饰符:
- 1.prevent:阻止默认事件(常用);
- 2.stop:阻止事件冒泡(常用);
- 3.once:事件只触发一次(常用);
- 4.capture:使用事件的捕获模式;
- 5.self:只有event.target是当前操作的元素时才触发事件;
- 6.passive:事件的默认行为立即执行,无需等待事件回调执行完毕;
a标签默认会跳转,阻止以后不会跳转
<!-- 阻止默认事件(常用) -->
<a href="https://www.bilibili.com/" @click.prevent="showInfo">点我提示信息</a>
事件只触发一次(常用)
<button @click.once="showInfo">点我提示信息</button>
2. 5、计数器
<body><div id="app"><button @click="sub">-</button><span>{{ num }}</span><button @click="add">+</button></div><script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script><script>var app=new Vue({el:"#app",data:{num:1},methods:{add:function(){if(this.num<=9){this.num++;}else{alert("数量已经达到上限啦!");}},sub:function(){if(this.num>=1){this.num--;}else{alert("数量已经达到下限啦!");}}}})</script>
</body>
2. 6、v-show
根据表达式的真假,切换元素的显示和隐藏
<div id="app">
<img src="#" alt="" v-show="true">
<img src="#" alt="" v-show="isShow">
<img src="#" alt="age>=18">
</div>
var app=new Vue({el:"#app",data:{isShow:false,age:16}
})
- v-show原理式修改元素的display,实现显示隐藏
- 指令后面的值,最后会被解析成布尔值
- 数据改变后,元素的显示状态会同步更新
<body><div id="app"><img src="/img/yellow.png" v-show="isShow"><button @click="doit">点击</button><img src="/img/yellow.png" v-show="num==5"><button @click="sub">-</button><span>{{num}}</span><button @click="add">+</button></div><script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script><script>var app=new Vue({el:"#app",data:{isShow:true,num:0},methods:{doit:function(){this.isShow=!this.isShow;},add:function(){this.num++;},sub:function(){this.num--;}}})</script>
</body>
2. 7、v-if
根据表达式的真假,切换元素的显示和隐藏(操作dom元素)
- 表达式的值为true,元素存在在dom中,为false,在dom树中移除
-频繁的切换使用v-show,消耗比较小,反之使用v-if
<body><!--if是直接移除样式,show是改变display--><div id="app"><p v-if="isShow">今天是星期六</p><button @click="clickIt">按钮</button><p v-if="num>=20">明天是星期天</p></div><script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script><script>var app=new Vue({el:"#app",data:{isShow:true,num:2},methods:{clickIt:function(){this.isShow=!this.isShow;}}})</script>
</body>
2. 8、v-bind
设置元素的属性(比如src,title,class)
- 完整写法是
v-bind:属性名
- 简写的华可以省略
v-bind
只保留:属性名
- 需要动态的增删class建议使用对象的方式
<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><style>.active{border: 10px solid red;}</style>
</head>
<body><div id="app"><img v-bind:src="imgSrc" alt="" :class="isActive?'active':''"@click="fan"><br><br><br><img :src="imgSrc" alt="" :title="imgT+'!!'" @click="fan" :class="{active:isActive}"></div><script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script><script>var app=new Vue({el:"#app",data:{imgSrc:"/img/yellow.png",imgT:"鸭子",isActive:false},methods:{fan:function(){this.isActive=!this.isActive;}}})</script>
</body>
2. 8.2、绑定样式
class 绑定
- :class=‘xxx’
- 表达式是字符串: ‘classA’
- 表达式是对象: {classA:isA, classB: isB}
- 表达式是数组: [‘classA’, ‘classB’]
style 绑定
- :style="{ color: activeColor, fontSize: fontSize + ‘px’ }"
- 其中 activeColor/fontSize 是 data 属性
<div id="root">
<!-- 绑定class样式--字符串写法,适用于:样式的类名不确定,需要动态指定 -->
<div class="basic" :class="mood" @click="changeMood">{{name}}</div> <br/><br/>
<!-- 绑定class样式--数组写法,适用于:要绑定的样式个数不确定、名字也不确定 -->
<div class="basic" :class="classArr">{{name}}</div> <br/><br/>
<!-- 绑定class样式--对象写法,适用于:要绑定的样式个数确定、名字也确定,但要动态决定用不用 -->
<div class="basic" :class="classObj">{{name}}</div> <br/><br/>
<!-- 绑定style样式--对象写法 -->
<div class="basic" :style="styleObj">{{name}}</div> <br/><br/>
<!-- 绑定style样式--数组写法 -->
<div class="basic" :style="styleArr">{{name}}</div>
</div>
2. 9、图片切换
<body><div id="app"><img :src="imgSrc[num]" alt=""><br><br><br><button v-show="num!=0" @click="sub">上一页</button><button v-show="num!=3" @click="add">下一页</button></div><script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script><script>var app=new Vue({el:"#app",data:{imgSrc:["/img/1.jpg","/img/2.jpg","/img/3.jpg","/img/4.jpg"],num:0},methods:{add:function(){this.num++;},sub:function(){this.num--;}}})</script>
</body>
2. 10、v-for
2.10.1、根据数据生成列表结构
- 数组经常和v-for结合使用
- v-for="(item, index) in xxx" :key=“yyy”
- item和index可以结合其他指令一起使用
- 数组长度的更新会同步到页面上,是响应式的
<body><div id="app"><button @click="add">增加数据</button><button @click="sub">移除数据</button><ul><li v-for="(item,index) in arr">{{item}}{{index+1}}</li></ul><h2 v-for="(it,index) in vegetable" :title="it.name">{{it.name}}</h2></div><script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script><script>var app=new Vue({el:"#app",data:{arr:["北京","广州","上海","深圳"],vegetable:[{name:"potato"},{name:"tomato"},{name:"cabage"}]},methods:{add:function(){this.vegetable.push({name:"peach"});},sub:function(){this.vegetable.shift();//移除最左边的}}})</script>
</body>
2.10.2、key的内部原理
面试题:react、vue中的key有什么作用?(key的内部原理)
- 虚拟DOM中key的作用:
key是虚拟DOM对象的标识,当数据发生变化时,Vue会根据【新数据】生成【新的虚拟DOM】, 随后Vue进行【新虚拟DOM】与【旧虚拟DOM】的差异比较,比较规则如下: - .对比规则:
(1).旧虚拟DOM中找到了与新虚拟DOM相同的key:
①.若虚拟DOM中内容没变, 直接使用之前的真实DOM!
②.若虚拟DOM中内容变了, 则生成新的真实DOM,随后替换掉页面中之前的真实DOM。
(2).旧虚拟DOM中未找到与新虚拟DOM相同的key
创建新的真实DOM,随后渲染到到页面。 - 用index作为key可能会引发的问题:
(1)若对数据进行:逆序添加、逆序删除等破坏顺序操作:会产生没有必要的真实DOM更新 ==> 界面效果没问题, 但效率低。
(2)如果结构中还包含输入类的DOM:会产生错误DOM更新 ==> 界面有问题。 - 开发中如何选择key?:
1.最好使用每条数据的唯一标识作为key, 比如id、手机号、身份证号、学号等唯一值。
2.如果不存在对数据的逆序添加、逆序删除等破坏顺序操作,仅用于渲染列表用于展示,用index作为key是没有问题的。
2.10.3、列表过滤
<!DOCTYPE html>
<html><head><meta charset="UTF-8" /><title>列表过滤</title><script type="text/javascript" src="../js/vue.js"></script></head><body><!-- 准备好一个容器--><div id="root"><h2>人员列表</h2><input type="text" placeholder="请输入名字" v-model="keyWord"><ul><li v-for="(p,index) of filPerons" :key="index">{{p.name}}-{{p.age}}-{{p.sex}}</li></ul></div><script type="text/javascript">Vue.config.productionTip = false//用computed实现new Vue({el:'#root',data:{keyWord:'',persons:[{id:'001',name:'马冬梅',age:19,sex:'女'},{id:'002',name:'周冬雨',age:20,sex:'女'},{id:'003',name:'周杰伦',age:21,sex:'男'},{id:'004',name:'温兆伦',age:22,sex:'男'}]},computed:{filPerons(){return this.persons.filter((p)=>{return p.name.indexOf(this.keyWord) !== -1})}}}) </script>
</html>
<!DOCTYPE html>
<html><head><meta charset="UTF-8" /><title>列表过滤</title><script type="text/javascript" src="../js/vue.js"></script></head><body><!-- 准备好一个容器--><div id="root"><h2>人员列表</h2><input type="text" placeholder="请输入名字" v-model="keyWord"><ul><li v-for="(p,index) of filPerons" :key="index">{{p.name}}-{{p.age}}-{{p.sex}}</li></ul></div><script type="text/javascript">Vue.config.productionTip = falsenew Vue({el:'#root',data:{keyWord:'',persons:[{id:'001',name:'马冬梅',age:19,sex:'女'},{id:'002',name:'周冬雨',age:20,sex:'女'},{id:'003',name:'周杰伦',age:21,sex:'男'},{id:'004',name:'温兆伦',age:22,sex:'男'}],filPerons:[]},watch:{keyWord:{immediate:true,handler(val){this.filPerons = this.persons.filter((p)=>{return p.name.indexOf(val) !== -1})}}}}) </script>
</html>
2. 10.4、列表排序
<!DOCTYPE html>
<html><head><meta charset="UTF-8" /><title>列表排序</title><script type="text/javascript" src="../js/vue.js"></script></head><body><!-- 准备好一个容器--><div id="root"><h2>人员列表</h2><input type="text" placeholder="请输入名字" v-model="keyWord"><button @click="sortType = 2">年龄升序</button><button @click="sortType = 1">年龄降序</button><button @click="sortType = 0">原顺序</button><ul><li v-for="(p,index) of filPerons" :key="p.id">{{p.name}}-{{p.age}}-{{p.sex}}<input type="text"></li></ul></div><script type="text/javascript">Vue.config.productionTip = falsenew Vue({el:'#root',data:{keyWord:'',sortType:0, //0原顺序 1降序 2升序persons:[{id:'001',name:'马冬梅',age:30,sex:'女'},{id:'002',name:'周冬雨',age:31,sex:'女'},{id:'003',name:'周杰伦',age:18,sex:'男'},{id:'004',name:'温兆伦',age:19,sex:'男'}]},computed:{filPerons(){const arr = this.persons.filter((p)=>{return p.name.indexOf(this.keyWord) !== -1})//判断一下是否需要排序if(this.sortType){arr.sort((p1,p2)=>{return this.sortType === 1 ? p2.age-p1.age : p1.age-p2.age})}return arr}}}) </script>
</html>
2.11、v-model
设置和获取表单元素的值(双向数据绑定)
- 绑定的数据会和表单元素的值相互关联
- v-model的三个修饰符:
(1)lazy:失去焦点再收集数据
(2)number:输入字符串转为有效的数字
(3)trim:输入首尾空格过滤v-model.trim="userInfo.account"
<body><div id="app"><button @click="setV">修改</button><input type="text"v-model="message" @keyup.enter="add"><h2>{{message}}</h2><!--双向数据绑定--></div><script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script><script>var app=new Vue({el:"#app",data:{message:"冲冲冲"},methods:{add:function(){alert(this.message);},setV:function(){this.message="不会的都可以学";alert(this.message);}}})</script>
</body>
2.11、v-cloak
v-cloak指令(没有值):
1.本质是一个特殊属性,Vue实例创建完毕并接管容器后,会删掉v-cloak属性。
2.使用css配合v-cloak可以解决网速慢时页面展示出{{xxx}}的问题。
<!DOCTYPE html>
<html><head><meta charset="UTF-8" /><title>v-cloak指令</title></head><script type="text/javascript"src="http://localhost:8080/resource/5s/vue.js"></script><body><!-- 准备好一个容器--><div id="root"><h2 v-cloak>{{name}}</h2></div></body><script type="text/javascript">console.log(1)new Vue({el:'#root',data:{name:'尚硅谷'}})</script>
</html>
这时会有js阻塞,5s后控制台才输出1
<!DOCTYPE html>
<html><head><meta charset="UTF-8" /><title>v-cloak指令</title></head><body><!-- 准备好一个容器--><div id="root"><h2 v-cloak>{{name}}</h2></div><script type="text/javascript"src="http://localhost:8080/resource/5s/vue.js"></script></body><script type="text/javascript">console.log(1)new Vue({el:'#root',data:{name:'尚硅谷'}})</script>
</html>
会有没解析的模板出现在页面,5秒后才渲染
在没设置样式前,网页还是会呈现为接管的代码,一旦vue接管了代码,v-cloak就会被删除,结合样式,可以让未接管的代码不显示,可以在网速过慢的时候,页面显示未解析的代码
<!DOCTYPE html>
<html><head><meta charset="UTF-8" /><title>v-cloak指令</title><style>[v-cloak]{display:none;}</style><!-- 引入Vue --></head><body><div id="root"><h2 v-cloak>{{name}}</h2></div><script type="text/javascript" src="http://localhost:8080/resource/5s/vue.js"></script></body><script type="text/javascript">console.log(1)Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。new Vue({el:'#root',data:{name:'尚硅谷'}})</script>
</html>
2.12、v-once
v-once指令:
1.v-once所在节点在初次动态渲染后,就视为静态内容了。
2.以后数据的改变不会引起v-once所在结构的更新,可以用于优化性能。
<!DOCTYPE html>
<html><head><meta charset="UTF-8" /><title>v-once指令</title><script type="text/javascript" src="../js/vue.js"></script></head><body><div id="root"><h2 v-once>初始化的n值是:{{n}}</h2><h2>当前的n值是:{{n}}</h2><button @click="n++">点我n+1</button></div></body><script type="text/javascript">Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。new Vue({el:'#root',data:{n:1}})</script>
</html>
2.12、v-pre
1.跳过其所在节点的编译过程。
2.可利用它跳过:没有使用指令语法、没有使用插值语法的节点,会加快编译。
<!DOCTYPE html>
<html><head><meta charset="UTF-8" /><title>v-pre指令</title><!-- 引入Vue --><script type="text/javascript" src="../js/vue.js"></script></head><body><div id="root"><h2 v-pre>Vue其实很简单</h2><h2 >当前的n值是:{{n}}</h2><button @click="n++">点我n+1</button></div></body><script type="text/javascript">Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。new Vue({el:'#root',data:{n:1}})</script>
</html>
会跳过其所在节点的编译过程,显示未解析的代码
<!DOCTYPE html>
<html><head><meta charset="UTF-8" /><title>v-pre指令</title><!-- 引入Vue --><script type="text/javascript" src="../js/vue.js"></script></head><body><div id="root"><h2 v-pre>Vue其实很简单</h2><h2 v-pre>当前的n值是:{{n}}</h2><button @click="n++" v-pre>点我n+1</button></div></body><script type="text/javascript">Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。new Vue({el:'#root',data:{n:1}})</script>
</html>
3、自定义指令
一、定义语法:
(1).局部指令:
new Vue({directives:{指令名:配置对象}或directives{指令名:回调函数}
})
(2).全局指令:
Vue.directive(指令名,配置对象) 或 Vue.directive(指令名,回调函数)
二、配置对象中常用的3个回调:
(1).bind:指令与元素成功绑定时调用。
(2).inserted:指令所在元素被插入页面时调用。
(3).update:指令所在模板结构被重新解析时调用。
三、备注:
1.指令定义时不加v-,但使用时要加v-;
2.指令名如果是多个单词,要使用kebab-case命名方式,不要用camelCase命名。
需求1:定义一个v-big指令,和v-text功能类似,但会把绑定的数值放大10倍。
<!DOCTYPE html>
<html><head><meta charset="UTF-8" /><script type="text/javascript" src="../js/vue.js"></script></head><body><div id="root"><h2>{{name}}</h2><h2>当前的n值是:<span v-text="n"></span> </h2><h2>放大10倍后的n值是:<span v-big="n"></span> </h2><button @click="n++">点我n+1</button></div></body>
<script type="text/javascript">Vue.config.productionTip = falsenew Vue({el:'#root',data:{name:'learn',n:1},directives:{big(element,binding){console.log(element,binding);}}})</script>
</html>
element是真实的dom,binding.value是1,一开始n等于1。由于v-big绑定的是“n”,所以expression显示为“n”
<span v-big="n">
<script type="text/javascript">Vue.config.productionTip = falsenew Vue({el:'#root',data:{name:'learn',n:1},directives:{big(element,binding){element.innerText=binding.value*10}}})</script>
big函数何时调用
自定义指令写成函数式时只有在下面两种方式下被调用
- 指令与元素成功绑定时(以上来)
- 指令所在模板被重新解析,像上面的如果只更改name属性的值,big函数还是会被调用。
需求2:定义一个v-fbind指令,和v-bind功能类似,但可以让其所绑定的input元素默认获取焦点。
<!DOCTYPE html>
<html><head><meta charset="UTF-8" /><script type="text/javascript" src="../js/vue.js"></script></head><body><div id="root"><h2>{{name}}</h2><h2>当前的n值是:<span v-text="n"></span> </h2><h2>放大10倍后的n值是:<span v-big="n"></span> </h2><button @click="n++">点我n+1</button><hr/><input type="text" v-fbind:value="n"></div></body>
<script type="text/javascript">Vue.config.productionTip = falsenew Vue({el:'#root',data:{name:'learn',n:1},directives:{big(element,binding){element.innerText=binding.value*10},fbind(element, binding){element.value=binding.value;element.focus();}}})</script>
</html>
页面初始化第一次的时候并没有获取焦点
因为input只是和find绑定,还没渲染到页面,所以element.focus()无效,第二次第三次点击按钮,n值变化,指令所在模板被重新解析,find函数被重新调用
写成对象式
//指令与元素成功绑定时(一上来)bind(element,binding){},//指令所在元素被插入页面时inserted(element,binding){},//指令所在的模板被重新解析时update(element,binding){}
<script type="text/javascript">Vue.config.productionTip = falsenew Vue({el:'#root',data:{name:'learn',n:1},directives:{big(element,binding){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>
完整写法
/* 'big-number'(element,binding){console.log('big',this) //注意此处的this是window
// console.log('big')
element.innerText = binding.value * 10
}, */
- 如果用破折号连接就要用上面的写法,如果写v-bigNumber不会生效
- 指令里的this指向的是window
<h2>放大10倍后的n值是:<span v-bigNumber="n"></span> </h2>
1.指令定义时不加v-,但使用时要加v-;
2.指令名如果是多个单词,要使用kebab-case命名方式,不要用camelCase驼峰命名法命名。
定义全局指令
//定义全局指令/* Vue.directive('fbind',{//指令与元素成功绑定时(一上来)bind(element,binding){element.value = binding.value},//指令所在元素被插入页面时inserted(element,binding){element.focus()},//指令所在的模板被重新解析时update(element,binding){element.value = binding.value}}) */
3、axios基本使用
- axios必须先导入才可以使用
- 使用get或者post方法即可发送对应的请求
- then方法中的回调函数会在请求成功或者失败时触发
- 通过回调函数的形参可以获取响应内容或者错误内容
<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><script src="https://cdn.bootcdn.net/ajax/libs/vue/3.0.7/vue.cjs.js"></script><script src="https://cdn.bootcdn.net/ajax/libs/axios/0.21.1/axios.js"></script>
</head>
<body><input type="button" value="get请求"><input type="button" value="post请求"><script>const input=document.querySelectorAll('input');input[0].onclick=function(){axios.get("https://autumnfish.cn/api/joke/list?num=3").then(response=>{console.log(response.data);},reason=>{console.log(reason);});}input[1].onclick=function(){axios.post("https://autumnfish.cn/api/user/reg",{username:'盐焗鹌鹑蛋'}).then(response=>{console.log(response);},reason=>{cosnole.log(reason);});}</script>
</body>
配合vue使用
- axios回调函数中this的指向已经发生了改变,无法访问到data中的数据
- 把this保存起来,回调函数中直接使用保存的this即可
<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>
</head>
<body><div id="app"><input type="button" value="获取笑话" @click="getJoke"><p>{{joke}}</p></div><script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script><script src="https://cdn.bootcdn.net/ajax/libs/axios/0.21.1/axios.js"></script><script>var app=new Vue({el:"#app",data:{joke:"笑话"},methods:{getJoke:function(){var _this=this;console.log(this.joke);axios.get("https://autumnfish.cn/api/joke").then(function(response){console.log(response);console.log(response.data);_this.joke=response.data;},function(reason){console.log(reason);});//methods里最好不要用箭头函数,this指向问题}}})</script>
</body>
4、 计算属性
- 1.定义:要用的属性不存在,要通过已有属性计算得来。
- 2.原理:底层借助了Objcet.defineproperty方法提供的getter和setter。
- 3.get函数什么时候执行?
(1).初次读取时会执行一次。
(2).当依赖的数据发生改变时会被再次调用。 - 4.优势:与
methods
实现相比,内部有缓存机制(复用),效率更高,调试方便。 - 5.备注:
1.计算属性最终会出现在vm上,直接读取使用即可。
2.如果计算属性要被修改,那必须写set函数去响应修改,且set中要引起计算时依赖的数据发生改变。
<!DOCTYPE html>
<html><head><meta charset="UTF-8" /><title>姓名案例_计算属性实现</title><script type="text/javascript" src="../js/vue.js"></script></head><body><div id="root">姓:<input type="text" v-model="firstName"> <br/><br/>名:<input type="text" v-model="lastName"> <br/><br/>测试:<input type="text" v-model="x"> <br/><br/>全名:<span>{{fullName}}</span> <br/><br/></div></body><script type="text/javascript">Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。const vm = new Vue({el:'#root',data:{firstName:'张',lastName:'三',x:'你好'},methods: {demo(){}},computed:{fullName:{get(){console.log('get被调用了')// console.log(this) //此处的this是vmreturn this.firstName + '-' + this.lastName},set(value){console.log('set',value)const arr = value.split('-')this.firstName = arr[0]this.lastName = arr[1]}}}})</script>
</html>
- get有什么作用?
当有人读取fullName时,get就会被调用,且返回值就作为fullName的值 - get什么时候调用?
1.初次读取fullName时。
2.所依赖的数据发生变化时。 - set什么时候调用?
1.当fullName被修改时。
4.1 简写
只读不改就用简写
完整写法
<script type="text/javascript">Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。const vm = new Vue({el:'#root',data:{firstName:'张',lastName:'三',},computed:{//完整写法fullName:{get(){console.log('get被调用了')return this.firstName + '-' + this.lastName},set(value){console.log('set',value)const arr = value.split('-')this.firstName = arr[0]this.lastName = arr[1]}} }})</script>
简写
<script type="text/javascript">Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。const vm = new Vue({el:'#root',data:{firstName:'张',lastName:'三',},computed:{fullName(){console.log('get被调用了')return this.firstName + '-' + this.lastName}}})</script>
5、监视属性
5.1、监视属性watch:
1.当被监视的属性变化时, 回调函数自动调用, 进行相关操作
2.监视的属性必须存在,才能进行监视!!
3.监视的两种写法:
(1).new Vue时传入watch配置
<!DOCTYPE html>
<html><head><meta charset="UTF-8" /><title>天气案例_监视属性</title><!-- 引入Vue --><script type="text/javascript" src="../js/vue.js"></script></head><body><div id="root"><h2>今天天气很{{info}}</h2><button @click="changeWeather">切换天气</button></div></body><script type="text/javascript">Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。const vm = new Vue({el:'#root',data:{isHot:true,},computed:{info(){return this.isHot ? '炎热' : '凉爽'}},methods: {changeWeather(){this.isHot = !this.isHot}},watch:{isHot:{immediate:true, //初始化时让handler调用一下//handler什么时候调用?当isHot发生改变时。handler(newValue,oldValue){console.log('isHot被修改了',newValue,oldValue)}}} })</script>
</html>
(2).通过vm.$watch监视
<!DOCTYPE html>
<html><head><meta charset="UTF-8" /><title>天气案例_监视属性</title><!-- 引入Vue --><script type="text/javascript" src="../js/vue.js"></script></head><body><div id="root"><h2>今天天气很{{info}}</h2><button @click="changeWeather">切换天气</button></div></body><script type="text/javascript">Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。const vm = new Vue({el:'#root',data:{isHot:true,},computed:{info(){return this.isHot ? '炎热' : '凉爽'}},methods: {changeWeather(){this.isHot = !this.isHot}},})vm.$watch('isHot',{immediate:true, //初始化时让handler调用一下//handler什么时候调用?当isHot发生改变时。handler(newValue,oldValue){console.log('isHot被修改了',newValue,oldValue)}})</script>
</html>
5.2、深度监视
(1).Vue中的watch默认不监测对象内部值的改变(一层)。
<!DOCTYPE html>
<html><head><meta charset="UTF-8" /><title>天气案例_深度监视</title><!-- 引入Vue --><script type="text/javascript" src="../js/vue.js"></script></head><body><div id="root"><h3>a的值是:{{numbers.a}}</h3><button @click="numbers.a++">点我让a+1</button><h3>b的值是:{{numbers.b}}</h3><button @click="numbers.b++">点我让b+1</button><button @click="numbers = {a:666,b:888}">彻底替换掉numbers</button></div></body><script type="text/javascript">const vm = new Vue({el:'#root',data:{isHot:true,numbers:{a:1,b:1,}},watch:{//监视多级结构中某个属性的变化'numbers.a':{handler(){console.log('a被改变了')}} }})</script>
</html>
(2).配置deep:true可以监测对象内部值改变(多层)。
<!DOCTYPE html>
<html><head><meta charset="UTF-8" /><title>天气案例_深度监视</title><!-- 引入Vue --><script type="text/javascript" src="../js/vue.js"></script></head><body><div id="root"><h3>a的值是:{{numbers.a}}</h3><button @click="numbers.a++">点我让a+1</button><h3>b的值是:{{numbers.b}}</h3><button @click="numbers.b++">点我让b+1</button><button @click="numbers = {a:666,b:888}">彻底替换掉numbers</button></div></body><script type="text/javascript">const vm = new Vue({el:'#root',data:{isHot:true,numbers:{a:1,b:1,}},watch:{//监视多级结构中所有属性的变化numbers:{//deep:true,handler(){console.log('numbers改变了')}}}})</script>
</html>
如果不加deep属性,改变a和b也不会有影响,因为监测的是对象的地址,对象的地址并没有改变
备注:
(1).Vue自身可以监测对象内部值的改变,但Vue提供的watch默认不可以,除非加deep属性!
(2).使用watch时根据数据的具体结构,决定是否采用深度监视。
5.3、简写
只需要handle的时候
<!DOCTYPE html>
<html><head><meta charset="UTF-8" /><title>天气案例_监视属性_简写</title><!-- 引入Vue --><script type="text/javascript" src="../js/vue.js"></script></head><body><div id="root"><h2>今天天气很{{info}}</h2><button @click="changeWeather">切换天气</button></div></body><script type="text/javascript">Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。const vm = new Vue({el:'#root',data:{isHot:true,},computed:{info(){return this.isHot ? '炎热' : '凉爽'}},methods: {changeWeather(){this.isHot = !this.isHot}},watch:{//简写/* isHot(newValue,oldValue){console.log('isHot被修改了',newValue,oldValue,this)} */}})//简写,不可以写箭头函数/* vm.$watch('isHot',function(newValue,oldValue){console.log('isHot被修改了',newValue,oldValue,this)}) */</script>
</html>
5.4、computed和watch之间的区别
- 1.computed能完成的功能,watch都可以完成。
- 2.watch能完成的功能,computed不一定能完成,例如:watch可以进行异步操作。watch没有返回值可以用定时器。
- 3.两个重要的小原则:
1.所被Vue管理的函数,最好写成普通函数,这样this的指向才是vm或组件实例对象。
2.所有不被Vue所管理的函数(定时器的回调函数、ajax的回调函数等、Promise的回调函数),最好写成箭头函数,这样this的指向才是vm或组件实例对象。
<!DOCTYPE html>
<html><head><meta charset="UTF-8" /><title>姓名案例_watch实现</title><!-- 引入Vue --><script type="text/javascript" src="../js/vue.js"></script></head><body><div id="root">姓:<input type="text" v-model="firstName"> <br/><br/>名:<input type="text" v-model="lastName"> <br/><br/>全名:<span>{{fullName}}</span> <br/><br/></div></body><script type="text/javascript">const vm = new Vue({el:'#root',data:{firstName:'张',lastName:'三',fullName:'张-三'},watch:{firstName(newName){setTimeout(()=>{console.log(this)this.fullName = newName + '-' + this.lastName},1000);},lastName(newName){this.fullName = this.firstName + '-' + newName}}})</script>
</html>
5.5、监视数据原理
Vue监视数据的原理:
- vue会监视data中所有层次的数据。
- 如何监测对象中的数据?
通过setter实现监视,且要在new Vue时就传入要监测的数据。
(1).对象中后追加的属性,Vue默认不做响应式处理
(2).如需给后添加的属性做响应式,请使用如下API:
Vue.set(target,propertyName/index,value) 或
vm.$set(target,propertyName/index,value) - 如何监测数组中的数据?
通过包裹数组更新元素的方法实现,本质就是做了两件事:
(1).调用原生对应的方法对数组进行更新。
(2).重新解析模板,进而更新页面。 - 在Vue修改数组中的某个元素一定要用如下方法:
(1)使用这些API:push()、pop()、shift()、unshift()、splice()、sort()、reverse()
(2)Vue.set() 或 vm.$set()
特别注意:Vue.set() 和 vm.$set() 不能给vm 或 vm的根数据对象 添加属性!!
6、生命周期
1.又名:生命周期回调函数、生命周期函数、生命周期钩子。
2.是什么:Vue在关键时刻帮我们调用的一些特殊名称的函数。
3.生命周期函数的名字不可更改,但函数的具体内容是程序员根据需求编写的。
4.生命周期函数中的this指向是vm 或 组件实例对象。
<!DOCTYPE html>
<html><head><meta charset="UTF-8" /><title>引出生命周期</title><!-- 引入Vue --><script type="text/javascript" src="../js/vue.js"></script></head><body><div id="root"><h2 v-if="a">你好啊</h2><h2 :style="{opacity}">欢迎学习Vue</h2></div></body><script type="text/javascript">Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。new Vue({el:'#root',data:{a:false,opacity:1},methods: {},//Vue完成模板的解析并把初始的真实DOM元素放入页面后(挂载完毕)调用mountedmounted(){console.log('mounted',this)setInterval(() => {this.opacity -= 0.01if(this.opacity <= 0) this.opacity = 1},16)},})//通过外部的定时器实现(不推荐)/* setInterval(() => {vm.opacity -= 0.01if(vm.opacity <= 0) vm.opacity = 1},16) */</script>
</html>
Vue完成模板的解析并把初始的真实DOM元素放入页面后(挂载完毕)调用mounted
<!DOCTYPE html>
<html><head><meta charset="UTF-8" /><script type="text/javascript" src="../js/vue.js"></script></head><body><!-- 准备好一个容器--><div id="root" :x="n"><h2 v-text="n"></h2><h2>当前的n值是:{{n}}</h2><button @click="add">点我n+1</button><button @click="bye">点我销毁vm</button></div></body><script type="text/javascript">new Vue({el:'#root',// template:`// <div>// <h2>当前的n值是:{{n}}</h2>// <button @click="add">点我n+1</button>// </div>// `,//只能一个根节点data:{n:1},methods: {add(){console.log('add')this.n++},bye(){console.log('bye')this.$destroy()}},watch:{n(){console.log('n变了')}},beforeCreate() {console.log('beforeCreate')},created() {console.log('created')},beforeMount() {console.log('beforeMount')},mounted() {console.log('mounted')},beforeUpdate() {console.log('beforeUpdate')},updated() {console.log('updated')},beforeDestroy() {console.log('beforeDestroy')},destroyed() {console.log('destroyed')},})</script>
</html>
点击销毁以后按按钮,依然有效,vue通过dom绑定方法,即使销毁了,方法依旧还绑定着,可以继续使用
常用的生命周期钩子:
1.mounted: 发送ajax请求、启动定时器、绑定自定义事件、订阅消息等【初始化操作】。
2.beforeDestroy: 清除定时器、解绑自定义事件、取消订阅消息等【收尾工作】。
关于销毁Vue实例
1.销毁后借助Vue开发者工具看不到任何信息。
2.销毁后自定义事件会失效,但原生DOM事件依然有效。
3.一般不会在beforeDestroy操作数据,因为即便操作数据,也不会再触发更新流程了。
7、模块与组件
模块
- 理解: 向外提供特定功能的 js 程序, 一般就是一个 js 文件
- 为什么: js 文件很多很复杂
- 作用: 复用 js, 简化 js 的编写, 提高 js 运行效率
组件
- 理解: 用来实现局部(特定)功能效果的代码集合(html/css/js/image……)
- 为什么: 一个界面的功能很复杂
- 作用: 复用编码, 简化项目编码, 提高运行效率
模块化
当应用中的 js 都以模块来编写的, 那这个应用就是一个模块化的应用。
组件化
当应用中的功能都是多组件的方式来编写的, 那这个应用就是一个组件化的应用,
7.1、非单文件组件
一个文件中包含n个组件
1.模板编写没有提示
- 没有构建过程, 无法将 ES6 转换成 ES5
- 不支持组件的 CSS
- 真正开发中几乎不用
Vue中使用组件的三大步骤:
7.1.1、定义组件(创建组件)
使用Vue.extend(options)创建,其中options和new Vue(options)时传入的那个options几乎一样,但也有点区别;
区别如下:
- 1.el不要写,为什么? ——— 最终所有的组件都要经过一个vm的管理,由vm中的el决定服务哪个容器。
- 2.data必须写成函数,为什么? ———— 避免组件被复用时,数据存在引用关系。 备注:使用template可以配置组件结构。
7.1.2、注册组件
- 1.局部注册:靠new Vue的时候传入components选项
- 2.全局注册:靠Vue.component(‘组件名’,组件)
7.1.3、使用组件(写组件标签)
<school></school>
<!DOCTYPE html>
<html><head><meta charset="UTF-8" /><script type="text/javascript" src="../js/vue.js"></script></head><body><div id="root"><hello></hello><hr><h1>{{msg}}</h1><hr><!-- 第三步:编写组件标签 --><school></school><hr><!-- 第三步:编写组件标签 --><student></student></div><div id="root2"><hello></hello></div></body><script type="text/javascript">Vue.config.productionTip = false//第一步:创建school组件const school = Vue.extend({template:`<div class="demo"><h2>学校名称:{{schoolName}}</h2><h2>学校地址:{{address}}</h2><button @click="showName">点我提示学校名</button> </div>`,//必须使用函数式,使用对象式组件复用的时候数据会同步改变data(){return {schoolName:'北大',address:'北京'}},methods: {showName(){alert(this.schoolName)}},})//第一步:创建student组件const student = Vue.extend({template:`<div><h2>学生姓名:{{studentName}}</h2><h2>学生年龄:{{age}}</h2></div>`,data(){return {studentName:'张三',age:18}}})//第一步:创建hello组件const hello = Vue.extend({template:`<div> <h2>你好啊!{{name}}</h2></div>`,data(){return {name:'Tom'}}})//第二步:全局注册组件Vue.component('hello',hello)//创建vmnew Vue({el:'#root',data:{msg:'你好啊!'},//第二步:注册组件(局部注册)components:{school,student}})new Vue({el:'#root2',})</script>
</html>
7.1.3、注意点
1.关于组件名:
一个单词组成:
- 第一种写法(首字母小写):school
- 第二种写法(首字母大写):School
多个单词组成:
- 第一种写法(kebab-case命名):my-school
- 第二种写法(CamelCase命名):MySchool (需要Vue脚手架支持)
备注:
-组件名尽可能回避HTML中已有的元素名称,例如:h2、H2都不行。 - 可以使用name配置项指定组件在开发者工具中呈现的名字。
2.关于组件标签:
第一种写法:
第二种写法:
备注:不用使用脚手架时,会导致后续组件不能渲染。
3.一个简写方式:
const school = Vue.extend(options) 可简写为:const school = options
7.1.4、组件嵌套
<!DOCTYPE html>
<html><head><meta charset="UTF-8" /><title>组件的嵌套</title><!-- 引入Vue --><script type="text/javascript" src="../js/vue.js"></script></head><body><div id="root"></div></body><script type="text/javascript">const student = Vue.extend({name:'student',template:`<div><h2>学生姓名:{{name}}</h2> <h2>学生年龄:{{age}}</h2> </div>`,data(){return {name:'张三',age:18}}})//定义school组件const school = Vue.extend({name:'school',template:`<div><h2>学校名称:{{name}}</h2> <h2>学校地址:{{address}}</h2> <student></student></div>`,data(){return {name:'北大',address:'北京'}},//注册组件(局部)components:{student}})//定义hello组件const hello = Vue.extend({template:`<h1>{{msg}}</h1>`,data(){return {msg:'Hello!'}}})//定义app组件,包含hello和shool组件const app = Vue.extend({template:`<div> <hello></hello><school></school></div>`,components:{school,hello}})//创建vmnew Vue({template:'<app></app>',el:'#root',//注册组件(局部)components:{app}})</script>
</html>
7.1.5、VueComponent
- 上面的 school组件本质是一个名为
VueComponent
的构造函数,且不是程序员定义的,是Vue.extend生成的。 - 我们只需要写或,Vue解析时会帮我们创建school组件的实例对象,即Vue帮我们执行的:
new VueComponent(options)
。 - 特别注意:每次调用Vue.extend,返回的都是一个全新的VueComponent!!!!
- 关于this指向:
(1).组件配置中:data函数、methods中的函数、watch中的函数、computed中的函数 它们的this均是【VueComponent实例对象】。
(2).new Vue(options)
配置中:data函数、methods中的函数、watch中的函数、computed中的函数 它们的this均是【Vue实例对象】。 - VueComponent的实例对象,以后简称vc(也可称之为:组件实例对象)。Vue的实例对象,以后简称vm。
7.1.6、原型链
//定义一个构造函数
function Demo(){this.a = 1
this.b = 2
}
//创建一个Demo的实例对象
const d = new Demo()
console.log(Demo.prototype) //显示原型属性
console.log(d.__proto__) //隐式原型属性
console.log(Demo.prototype === d.__proto__)
程序员通过显示原型属性操作原型对象,追加一个x属性,值为99
Demo.prototype.x = 99
console.log('@',d) */
7.1.6、内置关系
1.一个重要的内置关系:VueComponent.prototype.__proto__ === Vue.prototype
实例的隐式原型属性,永远指向自己缔造者的原型对象
2.为什么要有这个关系:让组件实例对象(vc)可以访问到 Vue原型上的属性、方法。
7.2、单文件组件
一个简单的school组件
<template><div class="demo"><h2>名称:{{schoolName}}</h2><h2>地址:{{address}}</h2><button @click="showName">点击我显示学校名称</button></div>
</template>
<script>
export default{name:'School',data(){return{schoolName:"北大",address:"北京"}},methods:{showName(){alert(this.schoolName)}}
}
</script>
<style>
.demo{background-color:pink;
}
</style>
vscode安装了vetur后,快速生成vue模板
<v 然后回车
7.2.1、App.vue
<template><div><School></School><Student></Student></div>
</template><script>
//引入组件import School from './School.vue'import Student from './Student.vue'export default {name:"App2",
components:{School,Student
}}
</script><style></style>
main.js和App.vue配对
vue非常详细基基基基基础相关推荐
- 基,特征向量和基础解系
1.基 如果空间V中有n个线性无关的向量A1,A2,A3,-An可以线性地表示任何该空间中任意一个向量,则这n个向量是空间V的一个基.基,其实就是定义了一个空间. 易知,空间中有多个这样的基. 最简单 ...
- 【运筹学】单纯形法总结 ( 单纯形法原理 | 单纯形法流程 | 单纯形表 | 计算检验数 | 最优解判定 | 入基变量 | 出基变量 | 方程组同解变换 ) ★★★
文章目录 一.单纯形法原理 二.单纯形法流程 三.单纯形法案例一 1.线性规划示例 2.转化标准形式 3.查找初始基可行解 4.初始基可行解的最优解判定 5.第一次迭代 : 入基与出基变量选择 6.第 ...
- 【运筹学】线性规划问题的解 ( 可行解 | 可行域 | 最优解 | 秩的概念 | 极大线性无关组 | 向量秩 | 矩阵秩 | 基 | 基变量 | 非基变量 | 基解 | 基可行解 | 可行基 )
文章目录 I . 线性规划问题解 II . 可行解 与 可行域 III . 最优解 IV . 秩 的 概念 V . 基 的概念 VI . 基变量 与 非基变量 VII . 基解 VIII . 基可行解 ...
- 变基的风险以及如何用变基解决变基
转载请标明出处:http://blog.csdn.net/xx326664162/article/details/50724116 文章出自:薛瑄的博客 你也可以查看我的其他同类文章,也会让你有一定的 ...
- 【运筹学】线性规划 人工变量法 ( 人工变量法案例 | 初始单纯形表 | 检验数计算 | 入基变量 | 出基变量 )
文章目录 一.生成初始单纯形表 二.计算非基变量检验数 三.最优解判定 四.选择入基变量 五.选择出基变量 六.更新单纯形表 上一篇博客 [运筹学]线性规划 人工变量法 ( 单纯形法总结 | 人工变量 ...
- 【运筹学】线性规划 单纯形法 案例二 ( 第一次迭代 | 矩阵变换 | 检验数计算 | 最优解判定 | 入基变量 | 出基变量 )
文章目录 一.第一次迭代 : 进行行变换 二.第一次迭代 : 计算检验数 三.第一次迭代 : 最优解判定 四.第一次迭代 : 入基变量 五.第一次迭代 : 出基变量 [运筹学]线性规划 单纯形法 ( ...
- 【运筹学】线性规划数学模型 ( 知识点回顾 | 可行解 | 最优解 | 阶梯型矩阵 | 阶梯型矩阵向量 | 基 | 基向量 | 基变量 | 非基变量 )
文章目录 一.知识点回顾 1.线性规划三要素 2.线性规划一般形式 3.线性规划标准形式 二.线性规划解.可行解.最优解 三.阶梯型矩阵 四.阶梯型矩阵向量 五.基.基向量.基变量.非基变量 一.知识 ...
- 【运筹学】线性规划 单纯形法 ( 基矩阵 | 基变量 | 非基矩阵 | 非基变量 | 矩阵分块形式 | 逆矩阵 | 基解 | 基可行解 )
文章目录 I . 基矩阵 B II . 基向量 PjP_jPj III . 基变量 IV . 非基矩阵 NNN V . 系数矩阵分块形式 A=(BN)A = ( B N )A=(BN) VI . 基 ...
- 1-(2-甲氧基乙基)-3-乙基咪唑三氟甲基磺酸盐{[C22O1IM][TfO]}离子液体
1-(2-甲氧基乙基)-3-乙基咪唑三氟甲基磺酸盐{[C22O1IM][TfO]}离子液体 中文名称:1-(2-甲氧基乙基)-3-乙基咪唑三氟甲基磺酸盐离子液体 简称:{[C22O1IM][TfO]} ...
- meso-四(邻烷氧基苯基)卟啉合钴(meso-T(2-ROP)PCo);meso-四-(N-苄基)吡碇基卟啉锌(ZnTBPyP);离子型锰卟啉化合物[MnTTMAPP][PF6]5齐岳供应
meso-四(邻烷氧基苯基)卟啉合钴(meso-T(2-ROP)PCo);meso-四-(N-苄基)吡碇基卟啉锌(ZnTBPyP);离子型锰卟啉化合物[MnTTMAPP][PF6]5齐岳供应卟啉定制系 ...
最新文章
- crashpad 应用程序异常解决方案
- Java NIO (五) 管道 (Pipe)
- android常用代码
- uploadify.php 漏洞,PhotoStore “uploadify.php”任意文件上传漏洞
- 4源代码的下载和编译
- **【ci框架】精通CodeIgniter框架
- Centos7下安装Python3.5
- oracle建立表语句 主键,oracle 创建表sql语句,主键,自增长
- git rebase和 merge的区别
- java怎么制作网页_如何制作网页
- wincc 脚本 实现计算机重启,安装WINCC过程中提示需要重启电脑,请问如何解决?-工业支持中心-西门子中国...
- 狐妖小红娘服务器维护,3月7游戏更新公告 狐妖小红娘版本上线
- js实现手机摇一摇以及震动功能
- R语言基础指令和并行算法初识(上篇)
- 做大数据可视化分析的软件和工具有哪些?
- outlook邮件模板_如何在Microsoft Outlook中创建和使用电子邮件模板
- 电影数据库开发设计——基于jsp(使用eclipse-jee,mysql-front)
- python学习之路08(正则表达式和网络)
- uva 1645 count 水题
- platform.js