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 单向数据绑定

  1. 语法: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 双向数据绑定

  1. 语法:v-mode:value="xxx" 或简写为 v-model="xxx"
  2. 特点:数据不仅能从 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的两种写法

  1. 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')
  1. data有2种写法
    (1).对象式
    (2).函数式
    如何选择:目前哪种写法都可以,以后学习到组件时,data必须使用函数式,否则会报错。
  2. 一个重要的原则:
    由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模型

  1. M:模型(Model) :data中的数据
  2. V:视图(View) :模板代码
  3. VM:视图模型(ViewModel):Vue实例

观察发现:

  1. data中所有的属性,最后都出现在了vm身上。
  2. 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() 方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象。

  1. 语法
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 绑定

  1. :class=‘xxx’
  2. 表达式是字符串: ‘classA’
  3. 表达式是对象: {classA:isA, classB: isB}
  4. 表达式是数组: [‘classA’, ‘classB’]

style 绑定

  1. :style="{ color: activeColor, fontSize: fontSize + ‘px’ }"
  2. 其中 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的内部原理)

  1. 虚拟DOM中key的作用:
    key是虚拟DOM对象的标识,当数据发生变化时,Vue会根据【新数据】生成【新的虚拟DOM】, 随后Vue进行【新虚拟DOM】与【旧虚拟DOM】的差异比较,比较规则如下:
  2. .对比规则:
    (1).旧虚拟DOM中找到了与新虚拟DOM相同的key:
    ①.若虚拟DOM中内容没变, 直接使用之前的真实DOM!
    ②.若虚拟DOM中内容变了, 则生成新的真实DOM,随后替换掉页面中之前的真实DOM。
    (2).旧虚拟DOM中未找到与新虚拟DOM相同的key
    创建新的真实DOM,随后渲染到到页面。
  3. 用index作为key可能会引发的问题:
    (1)若对数据进行:逆序添加、逆序删除等破坏顺序操作:会产生没有必要的真实DOM更新 ==> 界面效果没问题, 但效率低。
    (2)如果结构中还包含输入类的DOM:会产生错误DOM更新 ==> 界面有问题。
  4. 开发中如何选择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函数何时调用
自定义指令写成函数式时只有在下面两种方式下被调用

  1. 指令与元素成功绑定时(以上来)
  2. 指令所在模板被重新解析,像上面的如果只更改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监视数据的原理:

  1. vue会监视data中所有层次的数据。
  2. 如何监测对象中的数据?
    通过setter实现监视,且要在new Vue时就传入要监测的数据。
    (1).对象中后追加的属性,Vue默认不做响应式处理
    (2).如需给后添加的属性做响应式,请使用如下API:
    Vue.set(target,propertyName/index,value) 或
    vm.$set(target,propertyName/index,value)
  3. 如何监测数组中的数据?
    通过包裹数组更新元素的方法实现,本质就是做了两件事:
    (1).调用原生对应的方法对数组进行更新。
    (2).重新解析模板,进而更新页面。
  4. 在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、模块与组件

模块

  1. 理解: 向外提供特定功能的 js 程序, 一般就是一个 js 文件
  2. 为什么: js 文件很多很复杂
  3. 作用: 复用 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. 基,特征向量和基础解系

    1.基 如果空间V中有n个线性无关的向量A1,A2,A3,-An可以线性地表示任何该空间中任意一个向量,则这n个向量是空间V的一个基.基,其实就是定义了一个空间. 易知,空间中有多个这样的基. 最简单 ...

  2. 【运筹学】单纯形法总结 ( 单纯形法原理 | 单纯形法流程 | 单纯形表 | 计算检验数 | 最优解判定 | 入基变量 | 出基变量 | 方程组同解变换 ) ★★★

    文章目录 一.单纯形法原理 二.单纯形法流程 三.单纯形法案例一 1.线性规划示例 2.转化标准形式 3.查找初始基可行解 4.初始基可行解的最优解判定 5.第一次迭代 : 入基与出基变量选择 6.第 ...

  3. 【运筹学】线性规划问题的解 ( 可行解 | 可行域 | 最优解 | 秩的概念 | 极大线性无关组 | 向量秩 | 矩阵秩 | 基 | 基变量 | 非基变量 | 基解 | 基可行解 | 可行基 )

    文章目录 I . 线性规划问题解 II . 可行解 与 可行域 III . 最优解 IV . 秩 的 概念 V . 基 的概念 VI . 基变量 与 非基变量 VII . 基解 VIII . 基可行解 ...

  4. 变基的风险以及如何用变基解决变基

    转载请标明出处:http://blog.csdn.net/xx326664162/article/details/50724116 文章出自:薛瑄的博客 你也可以查看我的其他同类文章,也会让你有一定的 ...

  5. 【运筹学】线性规划 人工变量法 ( 人工变量法案例 | 初始单纯形表 | 检验数计算 | 入基变量 | 出基变量 )

    文章目录 一.生成初始单纯形表 二.计算非基变量检验数 三.最优解判定 四.选择入基变量 五.选择出基变量 六.更新单纯形表 上一篇博客 [运筹学]线性规划 人工变量法 ( 单纯形法总结 | 人工变量 ...

  6. 【运筹学】线性规划 单纯形法 案例二 ( 第一次迭代 | 矩阵变换 | 检验数计算 | 最优解判定 | 入基变量 | 出基变量 )

    文章目录 一.第一次迭代 : 进行行变换 二.第一次迭代 : 计算检验数 三.第一次迭代 : 最优解判定 四.第一次迭代 : 入基变量 五.第一次迭代 : 出基变量 [运筹学]线性规划 单纯形法 ( ...

  7. 【运筹学】线性规划数学模型 ( 知识点回顾 | 可行解 | 最优解 | 阶梯型矩阵 | 阶梯型矩阵向量 | 基 | 基向量 | 基变量 | 非基变量 )

    文章目录 一.知识点回顾 1.线性规划三要素 2.线性规划一般形式 3.线性规划标准形式 二.线性规划解.可行解.最优解 三.阶梯型矩阵 四.阶梯型矩阵向量 五.基.基向量.基变量.非基变量 一.知识 ...

  8. 【运筹学】线性规划 单纯形法 ( 基矩阵 | 基变量 | 非基矩阵 | 非基变量 | 矩阵分块形式 | 逆矩阵 | 基解 | 基可行解 )

    文章目录 I . 基矩阵 B II . 基向量 PjP_jPj​ III . 基变量 IV . 非基矩阵 NNN V . 系数矩阵分块形式 A=(BN)A = ( B N )A=(BN) VI . 基 ...

  9. 1-(2-甲氧基乙基)-3-乙基咪唑三氟甲基磺酸盐{[C22O1IM][TfO]}离子液体

    1-(2-甲氧基乙基)-3-乙基咪唑三氟甲基磺酸盐{[C22O1IM][TfO]}离子液体 中文名称:1-(2-甲氧基乙基)-3-乙基咪唑三氟甲基磺酸盐离子液体 简称:{[C22O1IM][TfO]} ...

  10. meso-四(邻烷氧基苯基)卟啉合钴(meso-T(2-ROP)PCo);meso-四-(N-苄基)吡碇基卟啉锌(ZnTBPyP);离子型锰卟啉化合物[MnTTMAPP][PF6]5齐岳供应

    meso-四(邻烷氧基苯基)卟啉合钴(meso-T(2-ROP)PCo);meso-四-(N-苄基)吡碇基卟啉锌(ZnTBPyP);离子型锰卟啉化合物[MnTTMAPP][PF6]5齐岳供应卟啉定制系 ...

最新文章

  1. crashpad 应用程序异常解决方案
  2. Java NIO (五) 管道 (Pipe)
  3. android常用代码
  4. uploadify.php 漏洞,PhotoStore “uploadify.php”任意文件上传漏洞
  5. 4源代码的下载和编译
  6. **【ci框架】精通CodeIgniter框架
  7. Centos7下安装Python3.5
  8. oracle建立表语句 主键,oracle 创建表sql语句,主键,自增长
  9. git rebase和 merge的区别
  10. java怎么制作网页_如何制作网页
  11. wincc 脚本 实现计算机重启,安装WINCC过程中提示需要重启电脑,请问如何解决?-工业支持中心-西门子中国...
  12. 狐妖小红娘服务器维护,3月7游戏更新公告 狐妖小红娘版本上线
  13. js实现手机摇一摇以及震动功能
  14. R语言基础指令和并行算法初识(上篇)
  15. 做大数据可视化分析的软件和工具有哪些?
  16. outlook邮件模板_如何在Microsoft Outlook中创建和使用电子邮件模板
  17. 电影数据库开发设计——基于jsp(使用eclipse-jee,mysql-front)
  18. python学习之路08(正则表达式和网络)
  19. uva 1645 count 水题
  20. platform.js

热门文章

  1. SQL优化实战经典案例分析
  2. 基本功能之-微信支付申请
  3. 磁盘分区时扩展卷选项为灰色,分区失败
  4. DM P3 static 注意事项
  5. springMvc整合undertow容器
  6. SCI论文总重复率29%,单篇重复达到了4%,请问可以了吗?
  7. 今天竟然有人模仿我的QQ号进行骗钱
  8. 使用wpf引入资源文件,RichTestBox加载rtf文件
  9. DOM智能营销下如何实现QQ群批量拉人的运营模式
  10. 浙大九推计算机学院,2019浙大经管类九推专题精讲课(内含真题)