vue学习笔记(跟着代码学)

vue学习笔记

学习视频:https://www.bilibili.com/video/BV17j411f74d
鸣谢:感谢coderwhy老师

1.vue的options选项

options: 创建vue对象时传入的东西

var options = {
    
    
    el:'#app',
    data:{
    
    },
    methods:function(){
    
    
    } 
}
var vue = new Vue(options):
var vue = new Vue({
    
    
	//选项
	el:'#app',//sting|
    data:{
    
    },
    methods:{
    
    
    }
})

el:

  • 类型:string|HTMLElement(docuennt.queryElement())
  • 作用:决定之后的vue实例会管理哪一个DOM

data:

  • 类型:Object|Function(组件当中的data必须是一个Function)
  • 作用:Vue实例对象的数据对象

methods:

  • 类型:{[key:string]:Function}
  • 作用:定义属于Vue的一些方法,可以在其他地方调用,也可以在指令中使用

方法和函数的区别

函数(function):是一段代码,使用时通过名字来调用.

//求和函数
function sum(a,b){
    
    
	return a+b;
}
sum(1,2);

方法(method):特殊的函数,属于对象,通过对象.来调用

//定义一个对象,对象中定义的函数,叫做方法
var obj = {
    
    
	sum:function(a,b){
    
    
		return a+b;
	}
}
obj.sum(1,2);

2.vue的生命周期函数

beforeCreate:

  • vue实例初始化(init)之后,vue实例对象被创建之前调用的方法

created:

  • vue实例对象创建完成,调用的方法

beforeMount:

  • vue实例对象和DOM挂载之前调用的方法

mounted:

  • vue实例对象已经和DOM挂载,调用的方法

beforeupdate:

updated:

beforeDestroy:

  • vue实例对象销毁之前调用的方法

destroyed:

  • vue实例对象已销毁之后调用的方法

3.vue的插值操作

mustache(双大括号)语法:{ {}}

<h2>{
    
    {
    
    key}}</h2>

4.vue的指令

v-once: 不带任何参数,带有该指令的标签内的值不会被重新渲染,不再响应式变化
v-html: 将值中的标签进行解析,格式标签会被编译并展示,例<a>:表示链接格式
v-text: 相当于{ {}}语法,接受一个string类型的key,但是会将标签内的值全部覆盖,一般不用
v-pre: 带有该指令的标签将不会被编译,显示原标签内容
v-cloak: 在浏览器未编译出mustache标签时,不展示出来,编译结束时再展示

<!doctype html>
<html>
    <head>
    	<meta charset="UTF-8"/>
        <title>Vue</title>
		<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    </head>
	<body>
       <div id='app' v-cloak>
           <div>插值:{
    
    {
    
    message}}</div>
           <div v-once>v-once指令:{
    
    {
    
    message}}</div>
           <div>不使用v-html指令时:{
    
    {
    
    url}}</div>
           <div v-html="url">v-html指令:{
    
    {
    
    url}}</div>
		   <div v-text="message">v-text:</div>
       </div>
    </body>
	<script>
    	const app = new Vue({
    
    
            el:'#app',
            data:{
    
    
                message:"hello world",
                url:'<a href="http://www.baidu.com">www.baidu.com<a>'
            }
        })
		//app.message = "打开测试v-once";
    </script>
</html>

v-bind:

  • **作用: **动态绑定属性
  • 缩写: :
<!doctype html>
<html>
    <head>
        <meta charset="UTF-8"/>
        <title>Vue</title>
        <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    </head>
    <body>
       <div id='app'>
            <div>不使用v-bind:<a href="http://www.baidu.com">百度一下</a></div>
            <div>使用v-bind:<a v-bind:href="url">百度一下</a></div>
            <div>v-bind简写:<a :href="url">百度一下</a></div>
        </div>
    </body>
    <script>
        const app = new Vue({
    
    
            el:'#app',
            data:{
    
    
                message:"hello world",
                url:'http://www.baidu.com'
            }
        })
    </script>
</html>

v-bind:class

  • 作用: 动态绑定class
  • 简写: :class
<!doctype html>
<html>
    <head>
        <meta charset="UTF-8"/>
        <title>Vue</title>
        <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
        <style>
        .active{
    
    
           color:red;
        }
        </style>
    </head>
    <body>
       <div id='app'>
            <div class="active">不使用v-bind:class</div>
            <div v-bind:class="active">使用v-bind:class</div>
            <div :class="active">v-bind:class简写:</div>
            <div :class="{active:true,line:false}">通过对象语法方式控制class</div>
            <div>
                <div :class="{active:isActive,line:isLine}">通过对象语法加变量的方式控制class</div>
                <button v-on:click="btnClick">点击按钮修改变量,控制class</button>
            </div>
            <div>
                <div :class="getClasses()">将对象语法写到方法中调用</div>
                <button v-on:click="btnClick">点击按钮修改变量,控制class</button>
            </div>
            <div>
                <div :class="[active,line]">通过数组语法加变量的方式控制class</div>
            </div>
            <div>
                <div :class="getClasses2()">将数组语法写到方法中调用</div>
            </div>
        </div>
    </body>
    <script>
        const app = new Vue({
    
    
            el:'#app',
            data:{
    
    
                message:"hello world",
                active:'active',
                line:'aaaaa',
                isActive:true,
                isLine:false
            },
            methods:{
    
    
                btnClick:function(){
    
    
                    this.isActive = !this.isActive;
                },
                getClasses:function(){
    
    
                    return {
    
    active:this.isActive,line:this.isLine};
                },
                getClasses2:function(){
    
    
                    return [this.active,this.line]
                }
            }
        })
    </script>
</html>

v-bind:style

  • 作用: 动态绑定style
  • 简写: :style
<!doctype html>
<html>
    <head>
        <meta charset="UTF-8"/>
        <title>Vue</title>
        <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
        <style>
        .text{
    
    
           font-size:50px;
           color:red;
        }
        </style>
    </head>
    <body>
       <div id='app'>
            <div style="font-size: 50px">不使用v-bind:style</div>
            <div v-bind:style="{fontSize:'50px'}">使用v-bind:style</div>
            <!-- 值必须要带'',否则会被认为是变量 -->
            <div :style="{fontSize:'50px'}">v-bind:style简写:</div>
            <!-- 对象语法绑定,数组方法绑定 -->
            <div :style="{fontSize:finalSize}">v-bind:style:对象语法,变量控制</div>
            <div :style="getStyles()">v-bind:style:调用方法动态绑定style</div>
            <div :style="[baseStyle,baseStyle1]">v-bind:style:动态绑定style数组语法</div>
        </div>
    </body>
    <script>
        const app = new Vue({
    
    
            el:'#app',
            data:{
    
    
                finalSize:'100px',
                finalColor:'red',
                baseStyle:{
    
    backgroundColor:'green'},
                baseStyle1:{
    
    fontSize:'50px'}
            },
            methods:{
    
    
                getStyles:function(){
    
    
                    return {
    
    fontSize:this.finalSize,backgroundColor:this.finalColor};
                },
                getClasses2:function(){
    
    
                    return [this.active,this.line]
                }
            }
        })
    </script>
</html>

v-on:

  • 作用: 绑定事件监听器
  • 简写: @
<!doctype html>
<html>
    <head>
        <meta charset="UTF-8"/>
        <title>Vue</title>
        <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    </head>
    <body>
       <div id='app'>
            <h2>{
    
    {
    
    counter}}</h2>
            <button v-on:click="increment">+</button>
            <button v-on:click="decrement">-</button>
            <button @click="increment">简写+</button>
            <button @click="decrement">简写-</button>
            <br>
            <!-- 当调用的函数不需要参数的时候小阔号可以省略 -->
            <button @click="btnClick()">按钮1</button>
            <button @click="btnClick">按钮1</button>
            <br>
            <!-- 如果需要参数在绑定的时候加上小括号和入参即可,
                 如果省略了小括号,则vue会默认将浏览器产生的event事件对象当作参数传入到方法中 -->
            <button @click="btn2Click(123)">按钮2</button>
            <button @click="btn2Click">按钮2</button>
            <br>
            <!-- 方法定义时,我们需要event对象,同时有需要其他参数 -->
            <!-- 在调用方法时,如何手动的获取到浏览器参数的event对象:$event -->
            <button @click="btn3Click(abc,$event)">按钮3</button>
        </div>
    </body>
    <script>
        const app = new Vue({
    
    
            el:'#app',
            data:{
    
    
               counter:0,
               abc:123
            },
            methods:{
    
    
                increment(){
    
    
                    this.counter++
                },
                decrement(){
    
    
                    this.counter--
                },
                btnClick(){
    
    
                    console.log("btn1Click")
                },
                btn2Click(abc){
    
    
                    console.log('-----------',abc);
                },
                btn3Click(abc,event){
    
    
                    console.log(abc,event);
                }
            },
        })
    </script>
</html>

v-on常用的修饰符

  • .stop-调用event.stopPropagation():阻止事件冒泡
  • .prevent-调用event.preventDefault():阻止默认事件
  • .{keyCode|keyAlias}-只当事件是从特定键触发时才触发回调
  • .capture-把默认的冒泡变为捕获
  • .native-监听组件根元素的原生事件
  • .once-只触发一次回调

5.计算属性

<!doctype html>
<html>
    <head>
        <meta charset="UTF-8"/>
        <title>Vue</title>
        <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    </head>
    <body>
       <div id='app'>
            <h2>{
    
    {
    
    getFullName()}}</h2>
            <h2>{
    
    {
    
    fullName}}</h2>
        </div>
    </body>
    <script>
        const app = new Vue({
    
    
            el:'#app',
            data:{
    
    
               firstName:'zhangsan' ,
               lastName : "lisi"
            },
            computed:{
    
    
                fullName:function(){
    
    
                    return this.firstName + this.lastName;
                }
            },
            methods:{
    
    
                getFullName(){
    
    
                    return this.firstName + this.lastName;
                }
            },
        })
    </script>
</html>

计算属性和methods的对比

  • 当变量没有变化时,多次调用计算属性时,计算属性取的是缓存的值
  • methods每次调用都会调用,消耗更多的性能
<!doctype html>
<html>
    <head>
        <meta charset="UTF-8"/>
        <title>Vue</title>
        <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    </head>
    <body>
       <div id='app'>
            <h2>{
    
    {
    
    getFullName()}}</h2>
            <h2>{
    
    {
    
    getFullName()}}</h2>
            <h2>{
    
    {
    
    getFullName()}}</h2>
            <h2>{
    
    {
    
    getFullName()}}</h2>
            <br>
            <h2>{
    
    {
    
    fullName}}</h2>
            <h2>{
    
    {
    
    fullName}}</h2>
            <h2>{
    
    {
    
    fullName}}</h2>
            <h2>{
    
    {
    
    fullName}}</h2>
            <h2>{
    
    {
    
    fullName}}</h2>
        </div>
    </body>
    <script>
        const app = new Vue({
    
    
            el:'#app',
            data:{
    
    
               firstName:'zhangsan' ,
               lastName : "lisi"
            },
            computed:{
    
    
                fullName:function(){
    
    
                    console.log("计算属性");
                    return this.firstName + this.lastName;
                }
            },
            methods:{
    
    
                getFullName(){
    
    
                    console.log("methods方法");
                    return this.firstName + this.lastName;
                }
            },
        })
    </script>
</html>

6.条件渲染

v-if:
作用: 根据表达式的值决定对应的元素以及子元素会不会渲染
通常和 v-else-ifv-else 连用

<!doctype html>
<html>
    <head>
        <meta charset="UTF-8"/>
        <title>Vue</title>
        <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    </head>
    <body>
       <div id='app'>
            <h2 v-if="score>=90">优秀</h2>
            <h2 v-else-if="score>=80">良好</h2>
            <h2 v-else-if="score>=60">及格</h2>
            <h2 v-else>不及格</h2>
        </div>
    </body>
    <script>
        const app = new Vue({
    
    
            el:'#app',
            data:{
    
    
                score:90
            }
            
        })
    </script>
</html>

v-ifv-show的区别

  1. v-if 当条件为false时,包含v-if指令的元素,根本就不会存在于dom中
  2. v-show 当条件为false时,v-show只是给元素加了一个display:none 的行内样式
  3. 开发中如果元素需要频繁的切换展示或隐藏,使用v-show,如果只用于一次判断就展示或隐藏则使用v-if
  4. 注意,由于v-if会将元素从dom中删除和重新添加,所以频繁调用时如果使用v-if会消耗性能
<!doctype html>
<html>
    <head>
        <meta charset="UTF-8"/>
        <title>Vue</title>
        <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    </head>
    <body>
       <div id='app'>
            <h2 v-if="isShow" id='aaa'>{
    
    {
    
    message}}</h2>
            <h2 v-show="isShow" id='bbb'>{
    
    {
    
    message}}</h2>
        </div>
    </body>
    <script>
        const app = new Vue({
    
    
            el:'#app',
            data:{
    
    
                message:'你好啊',
                isShow:false
            }
        })
    </script>
</html>

7.列表渲染(循环遍历)

v-for:
作用: 循环遍历数组或者对象数据

注: 在遍历过程中,给对应的元素或者组件添加一个:key属性,用来做唯一标识

目的: 为了更高效的更新虚拟DOM

相关拓展: 当某一层有很多相同的节点时,也就是列表节点时,如果我们希望在节点中插入一个新的节点,vue通过Diff算法默认的执行方式是循环递归遍,如果每个节点都有一个唯一的标识,则可以通过对比key找到正确的位置区插入新的节点

  1. 遍历数组数据
<!doctype html>
<html>
    <head>
        <meta charset="UTF-8"/>
        <title>Vue</title>
        <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    </head>
    <body>
       <div id='app'>
       		<!-- 1.在遍历过程中,没有使用索引值(下标值)-->
            <ul>
           		<li v-for="item in names">{
    
    {
    
    item}}</li>
           	</ul>
			
			<!-- 2.在遍历的过程中,获取索引值-->
			<ul>
           		<li v-for="(item,index) in names">
                    {
    
    {
    
    index+1}}.{
    
    {
    
    item}}
                </li>
           	</ul>
        </div>
    </body>
    <script>
        const app = new Vue({
    
    
            el:'#app',
            data:{
    
    
                names:['why','kobe','james','curry']
            }
        })
    </script>
</html>
  1. 遍历对象数据
<!doctype html>
<html>
    <head>
        <meta charset="UTF-8"/>
        <title>Vue</title>
        <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    </head>
    <body>
       <div id='app'>
           <!--1.在遍历对象的过程中,如果只是获取一个值,那么获取到的是value-->
            <ul><li v-for="item in info">{
    
    {
    
    item}}</li></ul>		
                
           <!--2.获取key和value,格式: (value,key),value在前,key在后-->
            <ul><li v-for="(value,key) in info">{
    
    {
    
    value}}--{
    
    {
    
    key}}</li></ul>
                
            <!--3.获取key和value和index,格式:(value,key,index) -->
            <ul><li v-for="(value,key,index) in info">{
    
    {
    
    value}}--{
    
    {
    
    key}}--{
    
    {
    
    index}}</li></ul>
        </div>
    </body>
    <script>
        const app = new Vue({
    
    
            el:'#app',
			data:{
    
    
				info:{
    
    
				  name:'why',
				  age: 18,
				  height:1.81
				}
			}
        })
    </script>
</html>

数组中哪些方法是响应式的

vue是响应式的,修改数据的时候页面也会同步刷新,但当data是数组数据时,通过索引值修改数组中的元素的时候,页面不会刷新

<!doctype html>
<html>
    <head>
        <meta charset="UTF-8"/>
        <title>Vue</title>
        <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    </head>
    <body>
       <div id='app'>          
            <ul>
            	<li v-for="item in letters">{
    
    {
    
    item}}</li>
            </ul>
            <button @click="btnClick">按钮</button>
        </div>
    </body>
    <script>
        const app = new Vue({
    
    
            el:'#app',
			data:{
    
    
				letters:['B','A','C','E','D']
			},
			methods:{
    
    
				btnClick(){
    
    
					<!--数组中push,pop,shift,unshift,splice,sort,reverse响应式的 -->
					//1.push()方法:在数组最后添加一个或多个元素
					this.letters.push('aaa')
					//2.pop()方法:删除数组中的最后一个元素
					this.letters.pop()
					//3.shift()方法:删除数组中的第一个元素
					this.letters.shift()
					//4.unshift()方法:在数组最前面添加一个或多个元素
					this.letters.unshift()
					//5.splice(start)方法
					//splice作用:删除元素/插入元素/替换元素
					//删除元素:第二个参数传入你要删除几个元素,如果没有传就删除后面所有元素					
					this.letters.splice(start)
					//替换元素:第二个参数,表示我们要替换几个元素,后面是用于替换前面的元素
					this.lttters.splice(1,3,'m','n','l')
					//插入元素,第二个参数,出入0,并且后面跟上要插入的元素
					this.letters.splice(1,0,'x','y','z')
                    //6.sort()方法:排序
                    this.letters.sort()
					//7.reverse()方法:反转
					this.letters.reverse()
					
					
					//通过索引值修改数组中的元素(非响应式的)
					this.letters[0]='bbbb'
					//解决方案一:通过splice方法
					this.letters.splice(0,1,'bbbb')
					//解决方案二:通过vue内部实现的函数 
					//set(要修改的对象,索引值,修改后的值)
					Vue.set(this.letters,0,'bbbb')					
				}
			}
        })
    </script>
</html>

8.表单绑定

v-model: 实现表单元素和数据的双向绑定

v-model的实现原理,通过v-bind绑定响应式数据,v-on:input监听响应式数据的变化

<!doctype html>
<html>
    <head>
        <meta charset="UTF-8"/>
        <title>Vue</title>
        <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    </head>
    <body>
       <div id='app'>          
           <input type="text" v-model="message">{
    
    {
    
    message}}</input>
			<!--v-model的实现原理-->
		   <input type="text" :value="msg" @input="msg=$event.target.value">{
    
    {
    
    msg}}</input>
        </div>
    </body>
    <script>
        const app = new Vue({
    
    
            el:'#app',
			data:{
    
    
				message:'你好啊',
                msg:'你好啊'
			}		
        })
    </script>
</html>
  1. v-model 结合radio类型使用
<!doctype html>
<html>
    <head>
        <meta charset="UTF-8"/>
        <title>Vue</title>
        <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    </head>
    <body>
       <div id='app'>    
       	  <label for="male">
          	<input type="radio" id="male" name="sex" value="男" v-model="sex"></label>
          <label for="female">
          	<input type="radio" id="female" name="sex" value="女" v-model="sex"></label>
		  <h2>您选择的性别是:{
    
    {
    
    sex}}</h2>
        </div>
        
    </body>
    <script>
        const app = new Vue({
    
    
            el:'#app',
			data:{
    
    
				sex:'男'
			}		
        })
    </script>
</html>
  1. v-model结合checkbox类型使用
<!doctype html>
<html>
    <head>
        <meta charset="UTF-8"/>
        <title>Vue</title>
        <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    </head>
    <body>
       <div id='app'>
			
		 <!--1.checkbox单选框-->
       	 <label for="agree">
          <input type="checkbox" id="agree" v-model='isAgree'>同意协议
         </label>
         <h2>您选择的是{
    
    {
    
    isAgree}}</h2>
		 <button :disabled="!isAgree">下一步</button>
		 
		 <br>
		 <!--2.checkbox多选框-->
         <input type="checkbox" value="篮球" v-model="hobbies">篮球         
         <input type="checkbox"  value="足球" v-model="hobbies">足球
         <input type="checkbox"  value="排球" v-model="hobbies">排球      
         <input type="checkbox"  value="乒乓球" v-model="hobbies">乒乓球	
         <input type="checkbox"  value="羽毛球" v-model="hobbies">羽毛球 		  
		 <h2>您的爱好是:{
    
    {
    
    hobbies}}</h2>
		 
        </div>
        
    </body>
    <script>
        const app = new Vue({
    
    
            el:'#app',
			data:{
    
    
				isAgree:false,
				hobbies:[]
			}		
        })
    </script>
</html>
  1. v-model结合select使用
    • 单选:只能选中一个值
      • v-model绑定的是一个值
      • 选中一个option中的选项时,将对应的value赋值到绑定的值里
    • 多选:可以选中多个值
      • v-model绑定的是一个数组
      • 当选中多个option选项时,将选中的option对应的value添加到数组中
<!doctype html>
<html>
<head>
	<meta charset="UTF-8">
	<title>Vue</title>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
    <div id='app'>
        <!--1.选择一个-->
		<select name="abc" v-model="fruit">
			<option value="苹果" >苹果</option>
			<option value="香蕉" >香蕉</option>
			<option value="榴莲" >榴莲</option>
			<option value="葡萄" >葡萄</option>
		</select>
		<h2>您的选择的水果是:{
    
    {
    
    fruit}}</h2> 

		<!--2.选择多个-->
		<select name="abc" v-model="fruits" multiple>
			<option value="苹果" >苹果</option>
			<option value="香蕉" >香蕉</option>
			<option value="榴莲" >榴莲</option>
			<option value="葡萄" >葡萄</option>
		</select>
		<h2>您的选择的水果是:{
    
    {
    
    fruits}}</h2> 
     </div> 
	<script>
        const app = new Vue({
    
    
            el:'#app',
			data:{
    
    
				fruit:"香蕉",
                fruits:[]
			}		
        })
    </script>
</body>
</html>

vue的值绑定: 动态的给value赋值

<!doctype html>
<html>
    <head>
        <meta charset="UTF-8"/>
        <title>Vue</title>
        <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    </head>
    <body>
       <div id='app'>
			
		 <!--非值绑定,value的值是写死的-->
         <input type="checkbox" value="篮球" v-model="hobbies">篮球         
         <input type="checkbox"  value="足球" v-model="hobbies">足球
         <input type="checkbox"  value="排球" v-model="hobbies">排球      
         <input type="checkbox"  value="乒乓球" v-model="hobbies">乒乓球	
         <input type="checkbox"  value="羽毛球" v-model="hobbies">羽毛球 		  
		 <h2>您的爱好是:{
    
    {
    
    hobbies}}</h2>

		 <!--值绑定,数据动态绑定的-->
             
         <label v-for="item in originHobbies">
             <input type="checkbox" :value="item" :id="item" v-model="hobbies">{
    
    {
    
    item}}
         </laber>    
		 
        </div>
        
    </body>
    <script>
        const app = new Vue({
    
    
            el:'#app',
			data:{
    
    
				isAgree:false,
				hobbies:[],
                originHobbies:['篮球','足球','羽毛球','乒乓球','橄榄球']
			}		
        })
    </script>
</html>

v-model 修饰符的使用

<!doctype html>
<html>
    <head>
        <meta charset="UTF-8"/>
        <title>Vue</title>
        <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    </head>
    <body>
       <div id='app'>
       	 <!--1.修饰符:lazy,让原本响应式的数据在失去焦点或者回车的时候才更新-->
         <input type="text"  v-model.lazy="message">{
    
    {
    
    message}}
         
         <!--2.修饰符:number,v-model没有使用number修饰符时,绑定的值一旦发生变化,在赋值时总是string类型的-->
         <input type="number"  v-model="age1">{
    
    {
    
    age1}}
         <h2>{
    
    {
    
    age1}}-{
    
    {
    
    typeof age1}}</h2>
         
         <!--使用了number修饰符时,值的类型一定为number类型-->
         <input type="number"  v-model.number="age2">{
    
    {
    
    age2}}
         <h2>{
    
    {
    
    age2}}-{
    
    {
    
    typeof age2}}</h2>
         
         <!--3.修饰符:trim-->
         <input type="text" v-model="name">
         <h2>您输入的名字是:{
    
    {
    
    name}}</h2>
        </div>
        
    </body>
    <script>
        const app = new Vue({
    
    
            el:'#app',
			data:{
    
    
				message:"你好啊",
				age1:0,
				age2:0,
				name:""
			}		
        })
    </script>
</html>

9.vue中的组件

1.组件的使用

  • 创建组件构造器:Vue.extend()创建组件构造器
  • 注册组件:Vue.component()方法注册组件
  • 使用组件
<!doctype html>
<html>
	<head>
		<meta chartset="UTF-8">
		<title>Vue</title>
		<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
	</head>
	<body>
		
		<div id="app">
            <!--3.使用组件-->
			<my-cpn></my-cpn>
			<my-cpn></my-cpn>
		</div>
		<script>
			//1.创建组件构造器对象
			const cpnC = Vue.extend({
    
    
				template:
				`<div>
					<h2>我是标题</h2>
					<p>我是内容1</p>
					<p>我是内容2</p>
				</div>`
			})			
			//2.注册组件
			Vue.component('my-cpn',cpnC)

			const app = new Vue({
    
    
				el:"#app"
			})
		</script>
	</body>
</html>
  1. 全局组件和局部组件
<!doctype html>
<html>
	<head>
		<meta chartset="UTF-8">
		<title>Vue</title>
		<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
	</head>
	<body>
		
		<div id="app">
            <!--3.使用组件-->
			<cpn></cpn>
			<cpn></cpn>
		</div>
		
		<div id="app2">
			<cpn></cpn>
		</div>
		<script>
			//1.创建组件构造器对象
			const cpnC = Vue.extend({
    
    
				template:
				`<div>
					<h2>我是标题</h2>
					<p>我是内容1</p>
					<p>我是内容2</p>
				</div>`
			})			
			//2.注册组件(全局组件,意味着可以在多个Vue的实例下面使用)
			//Vue.component('my-cpn',cpnC)

			const app = new Vue({
    
    
				el:"#app",
				//局部组件(在vue实例内部挂载)
				components:{
    
    
					//cpn使用组件时的标签名
					cpn:cpnC
				}
			})
			
			const app2 = new Vue({
    
    
				el:"#app2"
			})
		</script>
	</body>
</html>
  1. 父组件和子组件

当组件与组件之间存在层级关系,而其中一种非常重要的关系就是父子组件的关系

<!doctype html>
<html>
	<head>
		<meta chartset="UTF-8">
		<title>Vue</title>
		<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
	</head>
	<body>
		
		<div id="app">
            <!--3.使用组件-->
			<cpn2></cpn2>
		</div>
				
		<script>
			//1.创建第一个组件构造器(子组件)
			const cpnC1 = Vue.extend({
    
    
				template:
				`<div>
					<h2>我是标题1</h2>
					<p>我是内容</p>			
				</div>`
			})	

			//2.创建第二个组件构造器(父组件)
			const cpnC2 = Vue.extend({
    
    
				template:
				`<div>
					<h2>我是标题2</h2>
					<p>我是内容</p>
					<cpn1></cpn1>
				</div>`,
				components:{
    
    
					cpn1:cpnC1
				}
			})	
			
            //root组件
			const app = new Vue({
    
    
				el:"#app",
				//局部组件(在vue实例内部注册)
				components:{
    
    
					//cpn使用组件时的标签名
					cpn2:cpnC2
				}
			})
			
		</script>
	</body>
</html>
  1. 组件的语法糖注册方式
<!doctype html>
<html>
	<head>
		<meta chartset="UTF-8">
		<title>Vue</title>
		<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
	</head>
	<body>
		
		<div id="app">
            <!--3.使用组件-->
            <my-cpn></my-cpn>
			<cpn1></cpn1>			
		</div>
				
		<script>
			
			//1.创建组件构造器对象
			const cpnC = Vue.extend({
    
    
				template:
				`<div>
					<h2>我是标题</h2>
					<p>我是内容1</p>
					<p>我是内容2</p>
				</div>`
			})

			//2.注册组件
			Vue.component('my-cpn',cpnC)

            //2.全局组件注册的语法糖(效果等同于分开写)
            Vue.component("cpn1",{
    
    
            	template:
				`<div>
					<h2>我是标题</h2>
					<p>我是内容1</p>
					<p>我是内容2</p>
				</div>`
            })
            			
            //root组件
			const app = new Vue({
    
    
				el:"#app",               
			})
			
		</script>
	</body>
</html>
  1. 组件模版的分离写法
    • 方法一: 使用script标签,注意:类型必须是text/x-template
    • 方法二: 使用template标签
<!doctype html>
<html>
	<head>
		<meta chartset="UTF-8">
		<title>Vue</title>
		<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
	</head>
	<body>
		
		<div id="app">
            <!--3.使用组件-->
			<cpn></cpn>
			<cpn1></cpn1>
		</div>
		
		<!--1.script标签,注意:类型必须是text/x-template-->
		<script type="text/x-template" id="cpn">
           <div>
				<h2>我是标题1</h2>
				<p>我是内容</p>			
			</div> 
        </script>
		
		<!--2.template标签-->
        <template id="cpn1">
            <div>
				<h2>我是标题2</h2>
				<p>我是内容</p>			
			</div> 
        </template>
		
		<script>
			
            //1.注册一个全局组件
			Vue.component('cpn',{
    
    
				template:"#cpn"
			})							
            
			Vue.component('cpn1',{
    
    
				template:"#cpn1"
			})
			
			const app = new Vue({
    
    
				el:"#app",				
			})
			
		</script>
	</body>
</html>
  1. 组件中的数据存放问题

    • 组件是一个单独功能模块的封装,这个模块儿有属于自己的HTML模板,也有属于自己的数据data
    • 组件不能直接访问Vue实例中的data,组件中有保存自己数据的地方
    • 组件对象也有data属性,只是data属性的类型必须是一个function,而且这个函数返回一个对象,对象内部保存着数据

    组件中的data属性为什么必须是function类型?

    简单来讲就是js的作用域,js中作用域分为,全局作用域,局部作用域.全局作用域中的变量是全局可访问并修改的,而局部作用域中的变量,外部是无法随意访问修改的,js里函数内的变量的作用域是局部的,这样才不会导致多次使用相同的组件时候,数据之间产生影响

<!doctype html>
<html>
	<head>
		<meta chartset="UTF-8">
		<title>Vue</title>
		<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
	</head>
	<body>
		
		<div id="app">         
			<cpn></cpn>			
		</div>		
						
        <template id="cpn">
            <div>
				<h2>{
    
    {
    
    title}}</h2>
				<p>我是内容</p>			
			</div> 
        </template>
		
		<script>
		          
			Vue.component('cpn',{
    
    
				template:"#cpn",
                //组件对象也有data属性,只是data属性的类型必须是一个function,而且这个函数返回一个对象,对象内部保存着数据
            	data(){
    
    
            		return {
    
    
                        title:"abc"
                    }
        		}
			})							
           						
			const app = new Vue({
    
    
				el:"#app",				
			})
			
		</script>
	</body>
</html>
  1. 父子组件的通信

    • 在组件中,使用选项props来声明需要从父级接收到的数据
    • props的值有两种方式:
      • 方式一:字符串数据,数组中的字符串就是传递时的名称
      • 方式二:对象,对象可以设置传递时的类型,也可以设置默认值等

    父传子

    <!doctype html>
    <html>
    	<head>
    		<meta chartset="UTF-8">
    		<title>Vue</title>
    		<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    	</head>
    	<body>
    		
    		<div id="app">         
    			<cpn :cmovies="movies" :cmessage="message" :child-my-message="msg"></cpn>			
    		</div>		
    						
            <template id="cpn">
                <div>
    				<h2>{
          
          {
          
          cmessage}}</h2>
    				<p>{
          
          {
          
          cmovies}}</p>
    				<ul v-for="item in  cmovies"><li>{
          
          {
          
          item}}</li></ul>
    			</div> 
            </template>
    		
    		<script>
    		          
    			Vue.component('cpn',{
          
          
    				template:"#cpn",
                    //方式一:字符串数据,
                	//props:['cmovies',"cmessage"], 
                    //方式二:对象
                    props:{
          
          
                      //1.类型限制
                      //cmovies:Array,
                      //cmessage:String
                      //2.提供一些默认值,以及必传值
                      cmessage:{
          
          
                          type:String,
                          default:'我很好',
                          required:true
                      },
                      //类型是对象或者数组时,默认值必须是一个函数
                      cmovies:{
          
          
                          type:Array,
                          //default:[] vue2.5.17以下正确,之后必须是一个函数,否则报错
                          default(){
          
          
                              return []
                          }
                      },
                      //子组件中定义的props的值如果是驼峰标识的,在使用的时候,需要用短横线分隔命名
                      //childMyMessage在使用时应该写为:child-my-message
                      childMyMessage:{
          
          
                          type:String,
                          default:''
                      }
                    }
    			})							
               						
    			const app = new Vue({
          
          
    				el:"#app",
                    data:{
          
          
                        message:"你好啊",
                        movies:["海王","海贼王","航海王"],
                        msg:"aaaaa"
                    }
    			})
    			
    		</script>
    	</body>
    </html>
    
    • 在组件中,通过自定义事件来进行子组件传递数据或者事件到父组件中

      什么时候需要自定义事件

      • 当子组件需要向父组件传递数据时,就需要用到自定义事件了
      • v-on不仅仅可以用于监听DOM事件,也可以用于组件间的自定义事件

      自定义事件的流程:

      • 在子组件中,通过$emit()来触发事件
      • 在父组件中,通过v-on来监听子组件事件

    子传父

    <!doctype html>
    <html>
    	<head>
    		<meta chartset="UTF-8">
    		<title>Vue</title>
    		<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    	</head>
    	<body>
    		
    		<div id="app">         
    			<cpn @item-click="cpnClick"></cpn>			
    		</div>		
    						
            <template id="cpn">
                <div>
    				<button v-for="item in categories" @click="btnClick(item)">
                     {
          
          {
          
          item.name}}   
                    </button>
    			</div> 
            </template>
    		
    		<script>
    		          
    			const cpn = {
          
          
                    template:"#cpn",
                    data(){
          
          
                        return {
          
          
                            categories:[
                                {
          
          id:'aaa',name:'热门推荐'},
                                {
          
          id:'bbb',name:'手机数码'},
                                {
          
          id:'ccc',name:'家用家电'},
                                {
          
          id:'ddd',name:'电脑办公'},
                            ]
                        }
                    },
                    methods:{
          
          
                        btnClick(item){
          
          
                            console.log("子组件触发自定义事件");
                            //自定义组件名必须全小写,因为v-on会将DOM中监听的事件自动转为全小写,此处定义为大写,无法生效
    						this.$emit("item-click",item);
                        }
                    }
                }				
               						
    			const app = new Vue({
          
          
    				el:"#app",
                    data:{
          
          
                       
                    },
                    components:{
          
          
                        cpn
                    },
    				methods:{
          
          
    					cpnClick(item){
          
          
    						console.log("父组件:"+item.name)
    					}
    				}
    			})
    			
    		</script>
    	</body>
    </html>
    
  2. 父子组件的访问方式

    • 父组件访问子组件:使用 c h i l d r e n 或 者 children或者 childrenrefs
    • 子组件访问父组件:使用$parent

    父访问子( c h i l d r e n 或 者 children或者 childrenrefs)

    <!doctype html>
       <html>
       	<head>
       		<meta chartset="UTF-8">
       		<title>Vue</title>
       		<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
       	</head>
       	<body>
       <!doctype html>
       <html>
       	<head>
       		<meta chartset="UTF-8">
       		<title>Vue</title>
       		<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
       	</head>
       	<body>   		
    	<div id="app">         
       			<cpn></cpn>
       			<cpn ref="aaa"></cpn>
       			<cpn></cpn>
       			<button @click="btnClick">按钮</button>
       		</div>		
            <template id="cpn">
                 <div>我是子组件</div> 
            </template>
    
       		<script>
       			const cpn = {
          
          
                       template:"#cpn",
                       data(){
          
          
                           return {
          
          
                              name:'我是子组件的name'
                           }
                       },
       				methods:{
          
          
       					showMessage(){
          
          
       						console.log('showMessage');
       					}
       				}
                   }				
                  						
       			const app = new Vue({
          
          
       				el:"#app",
                       data:{
          
          
                          
    
                       },
                       components:{
          
          
                           cpn
                       },
    
       				methods:{
          
          
       					btnClick(){
          
          
       					
       						//1.通过$children获取子组件的对象
       						//组件变化,组件的下标改变,易取错,取所有组件时可用
                               <!-- console.log(this.$children); -->
       						<!-- this.$children[0].showMessage(); -->
       						this.$children[0].name;
       						for(let c of this.$children){
          
          
       							console.log(c.name);
       							c.showMessage();
       						}
       						
       						//2.通过refs获取子组件对象
       						//在需要获取数据的子组件上定义一个ref属性,通过属性取子组件对象
       						console.log('通过refs获取子组件对象:'+this.$refs.aaa.name)
                           }
       				}
       			})
       			
       		</script>
       	</body>
       </html>
    

    子访问父($parent)

     <!doctype html>
       <html>
       	<head>
       		<meta chartset="UTF-8">
       		<title>Vue</title>
       		<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
       	</head>
       	<body>
       		
       		<div id="app">         
       			<cpn></cpn>					
       		</div>		
       						
               <template id="cpn">
       			<ccpn></ccpn>
               </template>
       		
       		<template id="ccpn">
       			<div>
       				<div>我是子组件</div>
       				<button @click="btnClick">按钮</button>
       			</div>
               </template>
       		
       		<script>
       			const ccpn = {
          
          
       				template:"#ccpn",
       				methods:{
          
          
       					btnClick(){
          
          
       						//1.子访问父组件$parent
       						console.log(this.$parent);
       						console.log(this.$parent.name);
       						
                               //2.访问根组件
       						console.log(this.$root);
                               console.log(this.$root.message);
       					}
       				}
       			}
                  	
       			const cpn = {
          
          
                       template:"#cpn",
       				data(){
          
          
       					return{
          
          
       						name:'我是cpn组件的name'
       					}
       				},
       				components:{
          
          
       					ccpn
       				}
                   }
       				
       			const app = new Vue({
          
          
       				el:"#app",
                       data:{
          
          
                         message:'我是根组件的message' 
                       },
                       components:{
          
          
                           cpn
                       },
       				methods:{
          
          
       					
       				}
       			})
       			
       		</script>
       	</body>
       </html>
    

10.插槽slot

插槽:父组件在使用子组件时,想传递一些特殊的内容,则在定义子组件的时候可以定义一个slot标签(插槽),就可用于接收父组件传递的内容了

组件的插槽使封装的组件更加具有扩展性

(2.6.0之前的用法)

  1. 基本使用,插槽位置的内容可以被替换
<!doctype html>
<html>
	<head>
		<meta chartset="UTF-8">
		<title>Vue</title>
		<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
	</head>
	<body>
		<!-- 1.插槽的基本使用<slot></slot> -->
		<!-- 2.插槽的默认值: <slot>button</slot> -->
		<!-- 3.如果有多个值,同时放到组件进行替换时,一起作为替换元素 -->
		<div id="app">         
			<cpn></cpn>
			<cpn><button>按钮</button></cpn>	
			<cpn><p>我是外部内容</p><button>按钮</button></cpn>	
		</div>		
						
        <template id="cpn">
			<div>
				<h2>我是组件</h2>
				<p>我是组件内容</p>
				<slot><button>默认按钮</button></slot>
			</div>
        </template>				
		
		<script>
			const cpn = {
    
    
                template:"#cpn",			
            }
				
			const app = new Vue({
    
    
				el:"#app",               
                components:{
    
    
                    cpn
                },
				
			})
			
		</script>
	</body>
</html>
  1. 具名插槽
<!doctype html>
<html>
	<head>
		<meta chartset="UTF-8">
		<title>Vue</title>
		<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
	</head>
	<body>		
		<div id="app">         
			<cpn><span slot="center">标题</span></cpn>

			<cpn><button slot="left">返回</button></cpn>
			
			<cpn><button slot="right">搜索</button></cpn>
		</div>		
						
        <template id="cpn">
			<div>
				<slot name="left"><span>左边</span></slot>
				<slot name="center"><span>中间</span></slot>
				<slot name="right"><span>右边</span></slot>
			</div>
        </template>				
		
		<script>
			const cpn = {
    
    
                template:"#cpn",			
            }
				
			const app = new Vue({
    
    
				el:"#app",               
                components:{
    
    
                    cpn
                },
				
			})
			
		</script>
	</body>
</html>
  1. 作用域插槽(父组件替换插槽的标签,但是内容由子组件提供的)

什么是编译作用域: 父级模板里的所有内容都是在父级作用域中编译的;子模板里的所有内容都是在子作用域中编译的。

<!doctype html>
<html>
	<head>
		<meta chartset="UTF-8">
		<title>Vue</title>
		<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
	</head>
	<body>		
		<div id="app">
            <!-- 这里的isShow的变量取的是app模版里的isShow,子组件会被加载出来 -->
			<cpn v-Show="isShow"></cpn>
		</div>		
						
        <template id="cpn">
			<div>
				<h2>我是子组件</h2>
				<p>哈哈哈</p>
				<!-- 这里的isShow的变量取的是组件模版里的isShow,所以下面的按钮无法被渲染出来 -->
				<button v-show="isShow">按钮</button>
			</div>
        </template>				
		
		<script>
			const cpn = {
    
    
                template:"#cpn",
                data(){
    
    
                	return {
    
    
                		isShow:false
                	}
                }
            }
				
			const app = new Vue({
    
    
				el:"#app",
                data:{
    
    
                	message:'你好啊!',
                	isShow:true
                },
                components:{
    
    
                    cpn
                },
				
			})
			
		</script>
	</body>
</html>

作用域插槽实例

<!doctype html>
<html>
	<head>
		<meta chartset="UTF-8">
		<title>Vue</title>
		<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
	</head>
	<body>		
		<div id="app">   
			<cpn></cpn>
			<!-- 错误示范,编译作用域,此处无法取到子组件内的pLanguage -->
			<!-- <cpn><span v-for="item in pLanguages"></span></cpn> --> 
			

			<cpn>
				<!-- 定义了一个slot-scope,slot是一个引用,目的是获取子组件中的pLanguages -->
				<template slot-scope="slot">
					<!-- 父组件替换插槽的标签,但是内容由子组件提供的 -->
					<span v-for="item in slot.data">{
    
    {
    
    item}} - </span>
					<br>
					<span>{
    
    {
    
    slot.data.join(" - ")}}</span>
				</template>
			</cpn>

		</div>		
						
        <template id="cpn">
			<div>
				<slot :data="pLanguages">
					<ul>
						<li v-for="item in pLanguages">{
    
    {
    
    item}}</li>
					</ul>
				</slot>
			</div>
        </template>				
		
		<script>
			const cpn = {
    
    
                template:"#cpn",
                data(){
    
    
                	return {
    
    
                		pLanguages:['JavaScript','C++','Java','C#','Python','Go','Swift']
                	}
                }
            }
				
			const app = new Vue({
    
    
				el:"#app",
                data:{
    
    
                	message:'你好啊!',
                	isShow:true
                },
                components:{
    
    
                    cpn
                },
				
			})
			
		</script>
	</body>
</html>

2.6.0之后的插槽与2.6.0之前的插槽的区别

  • 2.6.0之前使用的是slot 和slot-scope 两个属性,slot用来选择使用的插槽是哪一个,slot-scope定义一个引用,用来接收子组件传过来的值

  • 2.6.0后,使用v-slot指令替代了slot和slot-scope,写法为:v-slot:插槽名=引用名

<!doctype html>
<html>
	<head>
		<meta chartset="UTF-8">
		<title>Vue</title>
		<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
	</head>
	<body>		
		<div id="app">

			<!--1和例22.6.0之前使用普通插槽的两种用法,slot属性可写,可不写,带有slot属性则其值必为:default -->
			<cpn >
				<template slot-scope="slotProps">1:{
    
    {
    
    slotProps.data}}
				</template>	
			</cpn>   
			<cpn >
				<template slot="default" slot-scope="slotProps">2:{
    
    {
    
    slotProps.data}}
				</template>	
			</cpn>

			<!-- 2.6.0后slot和slot-scope属性被v-slot指令替代了 -->
			
			<!--3和例42.6.0后使用普通插槽的两种用法,v-slot之后default可写可不写 -->
			<cpn >
				<template v-slot="slotProps">3:{
    
    {
    
    slotProps.data}}
				</template>	
			</cpn>

			<cpn >
				<template v-slot:default="slotProps">4:{
    
    {
    
    slotProps.data}}
				</template>	
			</cpn>

			<!--5和例62.6.0后使用具名插槽的两种用法,v-slot之后写要使用的插槽的名字,=之后是插槽所有属性的引用 -->	
			<cpn >
				<template slot="title" slot-scope="slotProps">5:{
    
    {
    
    slotProps.data}},{
    
    {
    
    slotProps.info}},{
    
    {
    
    slotProps.msg}}
				</template>	
			</cpn>

			<cpn >
				<template v-slot:title="slotProps">6:{
    
    {
    
    slotProps.data}},{
    
    {
    
    slotProps.info}}
				</template>	
			</cpn>
		</div>		
						
        <template id="cpn">
			<div>
				<!-- 第一种没有定义name属性的,就是一个普通的插槽 -->				
				<slot :data="msg1"></slot>
				<!-- 第二种定义了name属性的,这是一个具名插槽 -->
				<slot name="title" :data="msg2" :info="msg3" msg="1111"></slot>				
			</div>
        </template>				
		
		<script>
			const cpn = {
    
    
                template:"#cpn",
                data(){
    
    
                	return {
    
    
                		msg1:'我是msg1',
                		msg2:'我是msg2',
                		msg3:'info数据'
                	}
                }
            }
				
			const app = new Vue({
    
    
				el:"#app",
                data:{
    
    
                	message:'你好啊!',
                },
                components:{
    
    
                    cpn
                },
				
			})
			
		</script>
	</body>
</html>

猜你喜欢

转载自blog.csdn.net/qq_36744553/article/details/109079688