vue基础

368 阅读22分钟

vue基础

一.第一个vue程序

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title>第一个vue程序</title>
	</head>
	<body>
		<div class="" id="app">
			<span>{{msg}}</span>
			<span>{{keywold}}</span>
			<button v-on:click="add">点击</button>
		</div>
		<script src="https://cdn.bootcss.com/vue/2.5.21/vue.js"></script>
		<script>
			var vm=new Vue({
				el:"#app",
				data:{//对象的格式
					msg:"你好世界",
					keywold:"我正在学习vue"
				},
				methods:{//对象的格式
					add(){
						console.log(this.msg);
					}
				}
			});
		</script>
	</body>
</html>

vue的第一个程序虽然简单,但是包含了vue的诸多基础的知识点,下面我们正式学习vue的基础知识

二.挂载

<script>
    var vm=new Vue({
        el:"#app",//挂载
        data:{
            msg:"你好世界",
            keywold:"我正在学习vue"
        },
        methods:{
            add(){
                console.log(this.msg);
            }
    	}
    });
</script>

在vue运行时会根据你挂载的是哪个DOM节点进行查找,该vue实例的数据将对该节点的区域起作用

三.插值表达式 {{}}

在vue中插值表达式的作用

  • 对象:{{{ name:'jack'}}}
  • 字符串:{{'hello world!'}}
  • 布尔值:{{isTrue==-1}}
  • 三元表达式:{{isTrue?'正确':'错误'}}
<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title>基础</title>
	</head>
	<body>
		<div class="" id="app">
                <p>{{ msg }}</p>
          	<p>{{ {name: 'jack'} }}</p>
          	<p>{{ 'Hello World!' }}</p>
          	<p>{{ isTrue == -1 }}</p>
          	<p>{{ isTrue ? '真' : '假' }}</p>
		</div>
		<script src="https://cdn.bootcss.com/vue/2.5.21/vue.js"></script>
		<script>
			var vm=new Vue({
				el:"#app",
				data:{
					msg:"你好世界",
					isTrue:true
				},
				methods:{
                                    add(){
                                        console.log(this.msg);
                                    }
				}
			});
		</script>
	</body>
</html>

四.指令 v-

  • v-text

  • v-html

  • v-if

  • v-else-if

  • v-else

  • v-show

  • v-bind

  • v-on

  • v-model

  • v-for

1.v-text v-html

  • v-text:把内容当做纯文本解析出来,不会解析HTML代码

  • v-html:可以解析HTML代码

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title>基础</title>
	</head>
	<body>
		<div class="" id="app">
		  	<p v-text="msg"></p>
          	<p v-html="msg"></p>
		</div>
		<script src="vue-2.4.0.js"></script>
		<script>
			var vm=new Vue({
				el:"#app",
				data:{
					msg:"<h1>你好世界</h1>",
				},
				methods:{
					add(){
						console.log(this.msg);
					}
				}
			});
		</script>
	</body>
</html>

2.v-if v-else-if v-else v-show

说明:

  • v-if v-show的功能类似,都是判断语句,如果条件成立则进行节点渲染
  • v-if 如果是假,则在 Element 中不会渲染
  • v-show 如果是假,则该标签为 display: none
  • 一般来说,v-if 有更高的切换开销,而 v-show 有更高的初始渲染开销。因此,如果需要非常频繁地切换,则使用 v-show 较好;如果在运行时条件很少改变,则使用 v-if 较好。
<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title>基础</title>
	</head>
	<body>
		<div class="" id="app">
                    <p v-if="tag>=90">成绩优秀</p>
                    <p v-else-if="tag>=60">成绩合格</p>
                    <p v-else="tag<60">成绩不合格</p>
                    <p v-show="msg==11">你可以毕业了!</p>
		</div>
		<script src="vue-2.4.0.js"></script>
		<script>
			var vm=new Vue({
				el:"#app",
				data:{
					tag:93,
					msg:11
				},
			});
		</script>
	</body>
	<!--结果-->
	<!--成绩合格-->
	<!--你可以毕业了-->
</html>

3.v-for v-bind v-model

说明:

  • v-for 是循环指令,如果有两个参数,v-for=(item,index) in arr, item表示数组的值,index表示数组的索引
  • v-bind是属性绑定指令,给某个元素绑定属性,数据流向:vue-html
  • v-model双向数据绑定,v-model 只能给具有 value 属性的元素进行双向数据绑定,一般为表单元素,数据流向:vue-html-vue
<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title>基础</title>
	</head>
	<body>
		<div class="" id="app">
			<input v-model="msg" ></input> 
			<input v-bind:type="type" v-bind:value="msg"></input>
			<p><span v-bind:style="style">你好呀,世界!</span></p>
		  	<table border="1" cellspacing="0" cellpadding="0">
		  		<tr>
		  			<th>编号</th>
		  			<th>科目</th>
		  			<th>成绩</th>
		  		</tr>
                <!--使用v-for时,一般要绑定一个key属性-->
		  		<tr v-for="v in course" v-bind:key="v.id">
		  			<th>{{v.id}}</th>
		  			<th>{{v.cname}}</th>
		  			<th>{{v.score}}</th>
		  		</tr>
		  		
		  	</table>
		</div>
		<script src="https://cdn.bootcss.com/vue/2.5.21/vue.js"></script>
		<script>
			var vm=new Vue({
				el:"#app",
				data:{
					course:[
						{id:1,cname:"语文",score:70},
						{id:2,cname:"数学",score:60},
						{id:3,cname:"英语",score:58},
						{id:4,cname:"生物",score:89},
						{id:5,cname:"化学",score:94}
					],
					msg:"2018-2019学年成绩",
					type:"button",
					style:"color:red;"
				}
			});
		</script>
	</body>
</html>

4.v-on

说明:

  • v-on,绑定的是事件,比如:v-on:click
  • v-on:click - 全写,@click - 简写
<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title>文字跑马灯</title>
		<style type="text/css">
			a{
                            display: inline-block;
                            padding: 4px;
                            border:1px solid #ccc;
                            cursor: pointer;
			}
		</style>
		<script src="https://cdn.bootcss.com/vue/2.5.21/vue.js"></script>
	</head>
	<body>
		<div class="box">
			<div>
                <a v-on:click.prevent="start">开始</a>
                <a v-on:click.prevent="stop">结束</a>				
            </div>
			<h2 v-html="msg"></h2>
		</div>
	
		<script>
			var vm=new Vue({
				el:(".box"),
				data:{
					msg:"我是幽灵小猫,你呢?",
					timer:null
				},
				methods:{
					start(){
						this.timer=setInterval(()=>{
							start=this.msg.substring(0,1);
							end=this.msg.substring(1);
							this.msg=end+start;
						},300)
					},
					stop(){
						clearInterval(this.timer);
					}
				}
			});
		</script>
	</body>
</html>

  • substring( )

    该方法用于提取字符串中介于两个指定下标之间的字符。

    返回值是一个新的字符串,该字符串值包含 stringObject 的一个子字符串,其内容是从 start 处到 stop-1 处的所有字符,startstop 大,那么该方法在提取子串之前会先交换这两个参数。

五.事件修饰符

  • .stop: 阻止冒泡
  • .prevent: 阻止默认事件
  • .capture 添加事件侦听器时使用事件捕获模式
  • .self 只当事件在该元素本身(比如不是子元素)触发时触发回调
  • .once 事件只触发一次

六.自定义指令

  • 自定义指令不详讲,这里举一个常用的例子

  • Vue.directive( dir_name , {} ) 定义全局自定义指令

  • directives{ dir_name : {} } 定义局部自定义指令


    // 自定义全局指令 v-focus,为绑定的元素自动获取焦点:

    Vue.directive('focus', {

      inserted: function (el) { // inserted 表示被绑定元素插入父节点时调用

        el.focus();

      }

    });

七.过滤器

  • 过滤器的作用是将后台传过来的数据进行过滤

  • 改变渲染结果,并返回过滤后的版本,不改变真正的data

  • 过滤器可以用在两个地方: 插值表达式v-bind 表达式。过滤器应该被添加在 JavaScript 表达式的尾部,由“管道”符指示

  • 过滤器可以分为全局过滤器和私有过滤器,vue本身有内置的过滤器,但是也可以自定义过滤器

1.私有过滤器

  • 私有局部过滤器,只能在 当前 VM 对象所控制的 View 区域进行使用
  • 写在VM对象里面
  • 关键字要加s
filters:{
    filterName:function(str){
         return ...;
    }
    //或者这样写
    filerName(){
        return...;
    }
  },

2.全局过滤器

  • 写在VM对象之外
  • 关键字不用加s
Vue.filter("filteName",function(str){
		return ...;
})

3.过滤器的使用

//在差值表达式中
{{msg | filterName()}}
//在v-bind表达式中
<div v-bind:id="rowId | filterName()"></div>

八.vue的生命周期

从两个方面理解:内部变化,外部渲染

  • 从vue实例创建,运行,到销毁期间总会伴随着各种各样的事件,这些事件统称为生命周期
  • 生命周期钩子:生命周期事件的别名

创建期间的生命周期函数:

  • beforeCreate:实例刚在内存中被创建出来,此时,还没有初始化好 data 和 methods 属性

  • created:实例已经在内存中创建OK,此时 data 和 methods 已经创建OK,此时还没有开始编译模板

  • beforeMount:此时已经完成了模板的编译,但是还没有挂载到页面中

  • mounted:此时,已经将编译好的模板,挂载到了页面指定的容器中显示

运行期间的生命周期函数:

  • beforeUpdate:状态更新之前执行此函数, 此时 data 中的状态值是最新的,但是界面上显示的 数据还是旧的,因为此时还没有开始重新渲染DOM节点
  • updated:实例更新完毕之后调用此函数,此时 data 中的状态值和界面上显示的数据,都已经完成了更新,界面已经被重新渲染好了!

销毁期间的生命周期函数:

  • beforeDestroy:实例销毁之前调用。在这一步,实例仍然完全可用。
  • destroyed:Vue 实例销毁后调用。调用后,Vue 实例指示的所有东西都会解绑定,所有的事件监听器会被移除,所有的子实例也会被销毁。

九.vue组件

1.什么是组件:

组件的出现,就是为了拆分Vue实例的代码量的,能够让我们以不同的组件,来划分不同的功能模块,将来我们需要什么样的功能,就可以去调用对应的组件即可; 组件化和模块化的不同:

  • 模块化: 是从代码逻辑的角度进行划分的;方便代码分层开发,保证每个功能模块的职能单一;
  • 组件化: 是从UI界面的角度进行划分的;前端的组件化,方便UI组件的重用;

2.组件的内容包括三个方面:

  • 组件的声明

  • 定义模板

  • 使用组件

3.组件的声明

全局组件

第一种方式

Vue.component('componentName',Vue.extend({
    
}))
<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title>基础</title>
	</head>
	<body>
		<div id="app">
            <!--使用组件-->
			<com1></com1>
		</div>
		
		<script src="https://cdn.bootcss.com/vue/2.5.21/vue.js"></script>
		<script>
			Vue.component('com1',Vue.extend({
            	//模板定义时一定要有一个根节点
				template:"<h3>我是第一种定义组件的方式</h3>"
			}))
			var vm=new Vue({
				el:"#app",
				data:{
					
				},
				methods:{
					
				}
			});
		</script>
	</body>
</html>

第二种方式

省略Vue.extend( )方法

Vue.component('componentName',{
    
})
<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title>基础</title>
	</head>
	<body>
		<div id="app">
			<!--使用组件-->
			<com2></com2>
		</div>
		
		<script src="https://cdn.bootcss.com/vue/2.5.21/vue.js"></script>
		<script>
			//模板定义时一定要有一个根节点
			Vue.component('com2',{
				template:"<div><span>这是第二种定义组件的方式</span></div>"
			})
			var vm=new Vue({
				el:"#app",
				data:{
					
				},
				methods:{
					
				}
			});
		</script>
	</body>
</html>

第三种方式

将模板的定义独立出来

Vue.component('com3',{
        template:"#temp1",
        template:"#temp2"
})
<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title>基础</title>
	</head>
	<body>
		<div id="app">
			<!--使用组件-->
			<com3></com3>
		</div>
		<!-- 在 被控制的 #app 外面,使用 template 元素,定义组件的HTML模板结构  -->
		<template id="temp1">
			<div>
				<h3>你好呀世界</h3>
			</div>
				
		</template>
		<template id="temp2">
			<div>
				<span>我是第三种定义组件的方法</span>
			</div>
		</template>
		
		
		<script src="https://cdn.bootcss.com/vue/2.5.21/vue.js"></script>
		<script>
			//模板定义时一定要有一个根节点
            //注意如果组件中有多个模板,在调用时该组件时只显示最后一个
			Vue.component('com3',{
                            template:"#temp1",
                            template:"#temp2"
			})
			var vm=new Vue({
				el:"#app",
				data:{
					
				},
				methods:{
					
				}
			});
		</script>
	</body>
</html>

私有组件
  • 关键词components

  • 私有组件只能在本身挂载的区域里使用

私有组件第一种写法

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title>基础</title>
	</head>
	<body>
		<div id="app">
			<!--使用组件-->
			<com1></com1>
			<login></login>
		</div>
		<!-- 在 被控制的 #app 外面,使用 template 元素,定义组件的HTML模板结构  -->
		<template id="temp1">
			<div>
				<h3>这是公共组件</h3>
			</div>
				
		</template>
		<template id="temp2">
			<div>
				<span>这是私有组件</span>
			</div>
		</template>
		
		
		<script src="https://cdn.bootcss.com/vue/2.5.21/vue.js"></script>
		<script>
			//公共组件
			Vue.component('com1',{
				template:"#temp1",
			})
			var vm=new Vue({
				el:"#app",
				data:{
					
				},
				methods:{
					
				},
				components:{//实例内部私有组件
					login:{
						template:"#temp2"
					}
				}
			});
		</script>
	</body>
</html>

私有组价的第二种写法

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title>基础</title>
		<script src="https://cdn.bootcss.com/vue/2.5.21/vue.js"></script>
  		<style>
  			
  		</style>
	</head>
	<body>
		
		<div id="app">
			<login></login>
			<account></account>
		</div>
		
		<template id="temp">
			<h3>我是第一个私有组件</h3>
		</template>
		
		<template id="temp1">
			<h3>我是第二个私有组件</h3>
		</template>

		<script>
			var login={//注意写法
				template:"#temp",
				data:function(){
					return{
						msg:0
					}
				}
			};
			var account={//注意写法
				template:"#temp1",
				data:function(){
					return{
						msg:0
					}
				}
			};

			var vm=new Vue({
				el:"#app",
				data:{
					tage:1
				},
				methods:{
					showdata(){
						alert(this.tage);
					}
				},
				components:{//注意写法,有多个组件
					login,
					account
				}
			});
		</script>
	</body>
</html>

十.组件中的data与vue实例的data的区别

  • 组件可以有自己的 data 数据
  • 组件的 data 和 实例的 data 有点不一样,实例中的 data 可以为一个对象,但是组件中的 data 必须是一个方法
  • 组件中的 data 除了必须为一个方法之外,这个方法内部,还必须返回一个对象才行
  • 组件中 的data 数据,使用方式,和实例中的 data 使用方式完全一样
<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title>基础</title>
	</head>
	<body>
		<div id="app">
			<!--使用组件-->
			<com1></com1>
		</div>
		<!-- 在 被控制的 #app 外面,使用 template 元素,定义组件的HTML模板结构  -->
		<template id="temp1">
			<div>
				<h3>{{msg2}}</h3>
			</div>
				
		</template>
        
		<script src="https://cdn.bootcss.com/vue/2.5.21/vue.js"></script>
		<script>
			//公共组件
			Vue.component('com1',{
				template:"#temp1",
				data:function(){
					return{
						msg2:"这是来自公共组件的data定义的数据"
					}
				}
			})
			var vm=new Vue({
				el:"#app",
				data:{
					msg1:"这是实例中的data"
				},
				methods:{
					
				}
			});
		</script>
	</body>
</html>

十一.组件传值

  • 组件分为私有组件,全局组件
  • 父组件向子组件传值,通过v-bind
  • 子组件向父组件传值,通过v-on

在学习组件传值之前必须要明白谁是父组件,谁是子组件

谁是私有的谁就是子组件

1.父组件向子组件传值

注意:一定要使用props属性来定义父组件传递过来的数据

父组件向子组件传值的描述(面试最爱)

口头描述:

  • 父组件通过子组件标签绑定一个属性,这个属性的值指向自己data的某个属性
  • 子组件中定义一个props属性,props的值是一个数组,存着父组件绑定的那个属性

书面描述:

  • 父组件通过标签上面定义传值 :eg='data'父组件中 data(){data:'egdata'}
  • 子组件通过props方法接受数据props:['eg']
<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title>基础</title>
	</head>
	<body>
		<div id="app">
			<com2 v-bind:pdata="msg"></com2>
		</div>
		
		<script src="https://cdn.bootcss.com/vue/2.5.21/vue.js"></script>
		
		<script>
			var vm=new Vue({
				el:"#app",
				data:{
					msg:"儿子,你要听话"
				},
				methods:{
					
				},
				components:{
					com2:{
						template:"<h3>{{this.msg2}}-----{{pdata}}</h3>",
						data:function(){
                            return {
                                msg2:"我是儿子,我已收到来自爸爸的话"
                            } 
						},
						props:["pdata"]
					},
				}
			});
		</script>
	</body>
</html>

2.子组件向父组件传值

子组件内部通过this.$emit('方法名', 要传递的数据)方式,来调用父组件中的方法,同时把数据传递给父组件使用

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title>基础</title>
	</head>
	<body>
		<div id="app">
			<!--传值给父组件-->
			<com2 @getdata='show'></com2>
		</div>
		
		<script src="https://cdn.bootcss.com/vue/2.5.21/vue.js"></script>
		
		<script>
			var vm=new Vue({
				el:"#app",
				methods:{
					show(val){
						alert(val);
						alert("儿子,你真不争气");
					}
				},
				components:{
					com2:{
						template:"<h3 @click='showdata'>{{msg2}}</h3>",
						
						data:function(){
							return {
								msg2:"我是儿子,点我看看我对爸爸说了什么"
							} 
						},
						methods:{
							showdata(){
								this.$emit('getdata','老爸,给点钱来花')//触发当前实例上的事件,并把值传出去
							}
						}
					},
				}
			});
		</script>
	</body>
</html>

十二.路由

在学习路由之前,我们来看看一下案例在没有使用路由知识是怎么实现的?

实现登录/注册的模块的切换

方法一:

v-if v-else

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title>基础</title>
	</head>
	<body>
		<div id="app">
			<a v-on:click="flag=true">登录</a>
			<a v-on:click="flag=false">注册</a>
			<div v-if="flag==true">
				<h3>登录模块</h3>
			</div>
			<div v-else="flag==false">
				<h3>注册模块</h3>
			</div>
		</div>
		
		<script src="https://cdn.bootcss.com/vue/2.5.21/vue.js"></script>
		<script>
			var vm=new Vue({
				el:"#app",
				data:{
					flag:true
				},
				methods:{
					
				}
			});
		</script>
	</body>
</html>

方法二:

组件的is属性

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title>基础</title>
	</head>
	<body>
		<div id="app">
			<a @click.prevent="comName='login'">登录</a>
			<a @click.prevent="comName='register'">注册</a>
			<component :is="comName"></component>
		</div>
		
		<script src="https://cdn.bootcss.com/vue/2.5.21/vue.js"></script>
		
		<script>
			Vue.component('login',{
				template:"<h3>登录模板</h3>"
			
			})
			Vue.component('register', {
      			template: '<h3>注册组件</h3>'
    		})
			
			
			Vue.component('login',{
				template:"<h3>登录模板</h3>"
			})
			Vue.component('register', {
	      		template: '<h3>注册组件</h3>'
	    	})
			var vm=new Vue({
				el:"#app",
				data:{
					comName:"login"//当前component中的:is绑定的组件的名称
				},
				methods:{
					
				}
			});
		</script>
	</body>
</html>

下面正式来学习路由

  • 路由是属于一个模块,在使用之前要引入,下面是cdn引入,也可以离线引入
  • 注意在引入路由模块之前要先引入vue库文件,否则路由模块不起作用
  <!-- Vue Router CDN - 管理路由 -->
  <script src="https://cdn.bootcss.com/vue-router/3.0.2/vue-router.js"></script>

1.路由基本模板

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title>基础</title>
		<script src="https://cdn.bootcss.com/vue/2.5.21/vue.js"></script>
		 <!-- Vue Router CDN - 管理路由 -->
  		<script src="https://cdn.bootcss.com/vue-router/3.0.2/vue-router.js"></script>
  		<style>
  			/*.router-link-active{
  				color:red;
  			}*/
  			.mystyle{
  				color:red;
  			}
  		</style>
	</head>
	<body>
		
		<div id="app">
			<router-link to="/login/李四/20">登录</router-link>//可以设置参数
			<router-link to="/register">注册</router-link>
			<!--占位符,用来显示匹配到的组件-->
			<router-view></router-view>
		</div>

		<script>
			var login=Vue.extend({
				template:"<h3>登录组件</h3>"
			});
			var register=Vue.extend({
				template:"<h3>注册组件</h3>"
			});
			var router=new VueRouter({//注意实例的名字要与下面的属性值要一致
				routes:[
					{path:"/",component:login},//根目录的状态下,默认加载login组件
					{path:"/login/:name/:age",component:login},
					{path:"/register",component:register}
				],
				linkActiveClass:'mystyle'
			});
		
			var vm=new Vue({
				el:"#app",
				router:router,//使用router属性来使用路由规则,注意属性值可以自定义
				
				
			});
		</script>
	</body>
</html>

2.路由的嵌套

<html>
	<head>
		<meta charset="utf-8">
		<title>路由的嵌套</title>
		<script src="https://cdn.bootcss.com/vue/2.5.21/vue.js"></script>
		 <!-- Vue Router CDN - 管理路由 -->
  		<script src="https://cdn.bootcss.com/vue-router/3.0.2/vue-router.js"></script>
	</head>
	<body>
		<div id="app">
			<router-link to="/account">点击我看看路由是怎么样嵌套的吧</router-link>
			<router-view></router-view>
		</div>
		<template id="temp">
			<div>
				<h1>下面是登录注册模块</h1>
				<router-link to="/account/login">登录</router-link>
				<router-link to="/account/reg">注册</router-link>
				<router-view></router-view>
			</div>
			
		</template>
		<script type="text/javascript">
			var account={
				template:"#temp"
			}
			var login={
				template:"<h3>我是登录</h3>"
			}
			var reg={
				template:"<h3>我是注册</h3>"
			}
			var router=new VueRouter({
				routes:[
					{
						path:"/account",
						component:account,
						children:[
							{path:"login",component:login},
							{path:"reg",component:reg}
						]
					}
				]
			});
			var vm=new Vue({
				el:"#app",
				router:router
			})
			
		</script>
	</body>
</html>

十三.render渲染组件与传统组件使用的区别

  • 传统组件的使用并不会覆盖原先挂载区域的其他的内容
  • render渲染组件会覆盖原先挂载区域的其他的内容

传统组件的写法

<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<script src="https://cdn.bootcss.com/vue/2.5.21/vue.js"></script>
	</head>
	<body>
		<div id="app">
			<h1>我是挂载区域的标签</h1>
			<login></login>
		</div>
		<template id="temp">
			<div>
				<h1>登录</h1>
			</div>
			
		</template>
		<script type="text/javascript">
	
			var vm=new Vue({
				el:"#app",
				components:{
					login:{
						template:"#temp"
					}
				}
			})
		</script>
	</body>
</html

render渲染组件

注意:使用render 渲染组件,组件的定义要写在vue实例外面

<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<script src="https://cdn.bootcss.com/vue/2.5.21/vue.js"></script>
	</head>
	<body>
		<div id="app">
			<h1>我是挂载区域的标签</h1>
			<login></login>
		</div>
		<template id="temp">
			<div>
				<h1>登录</h1>
			</div>
		</template>
		<script type="text/javascript">
			var login={//注意这种写法
				template:"#temp"
			}
			var vm=new Vue({
				el:"#app",
				render:function(createElements){//createElements是一个方法,调用它可以把指定的模板渲染成html结构
					return createElements(login)// return 的结果,会 替换页面中 el 指定的那个 容器
				}
			})
		</script>
	</body>
</html>

在使用render渲染组件,一般会这么简写:

9+render:c=>c(longin)

十四.监听属性 watch

  • watch是属性监听器,一般用来监听属性的变化
  • 当监听属性的值发生变化时,调用对应的方法
  • 需要在数据变化时执行异步或开销较大的操作时,这个方式是最有用的
<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title>基础</title>
		<script src="https://cdn.bootcss.com/vue/2.5.21/vue.js"></script>
  		<style>
  			
  		</style>
	</head>
	<body>
		
		<div id="app">
			<input type="text" v-model="tage"/>
			<p><span>{{tage}}</span></p>
			<button v-on:click="showdata">点击</button>
		</div>

		<script>
			var vm=new Vue({
				el:"#app",
				data:{
					tage:1
				},
				methods:{
					showdata(){
						console.log(this.tage);
					}
				},
				watch:{
                    //格式
                    //监控的属性:属性变化执行的函数
					tage:function(newVal,oldVal){
						//获取监控属性的新旧值
//						console.log(newVal);
//						console.log(oldVal);
                        console.log(this.tage);
					},
				}
			});
		</script>
	</body>
</html>

在写法上,监控一个属性还可以这么写,只是我们写成上面的那种形式语义更好

tage(){
    //获取监控属性的新旧值
    //console.log(newVal);
    //console.log(oldVal);
    console.log(this.tage);
}

十五.计算属性computed

1.什么情况下使用计算属性

模板内的表达式非常便利,但是设计它们的初衷是用于简单运算的。在模板中放入太多的逻辑会让模板过重且难以维护。例如:

js<div id="example">
  {{ message.split('').reverse().join('') }}
</div>

在这个地方,模板不再是简单的声明式逻辑。你必须看一段时间才能意识到,这里是想要显示变量 message 的翻转字符串。当你想要在模板中多次引用此处的翻转字符串时,就会更加难以处理。

所以,对于任何复杂逻辑,你都应当使用计算属性 , 相关的逻辑放在计算属性中完成

2.计算属性的特点

  • computed的依赖值 , 也就是监测的值有多个 , 当其中的依赖值发生变化时 , 就会自动执行相应的函数
  • 计算属性的结果会被缓存,只要相关依赖未改变,只会返回之前的结果 , 除非依赖的响应式属性变化才会重新计算并且返回新的结果

3.基础例子

<div id="example">
  <p>Original message: "{{ message }}"</p>
  <p>Computed reversed message: "{{ reversedMessage }}"</p>
</div>
var vm = new Vue({
  el: '#example',
  data: {
    message: 'Hello'
  },
  computed: {
    // 计算属性的 getter
    reversedMessage: function () {
      // `this` 指向 vm 实例,reversedMessage依赖于this.message
      return this.message.split('').reverse().join('')
    }
  }
})

3.为什么第一次运行便自动执行了计算属性对应的函数

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title>基础</title>
		<script src="https://cdn.bootcss.com/vue/2.5.21/vue.js"></script>
  		<style>
  			
  		</style>
	</head>
	<body>
		
		<div id="app">
			<input type="text" v-model="str"/>
			<input type="text" v-model="msg"/>
			<p><span>{{newStr}}</span></p>
			<button v-on:click="showdata">点击</button>
		</div>

		<script>
			var vm=new Vue({
				el:"#app",
				data:{
					str:"hello",
					msg:'world',
					
				},
				methods:{
					showdata(){
						console.log(this.newStr);
					}
				},
				computed:{
					newStr:function(){
						return this.str+this.msg;
					}
				}
			});
		</script>
	</body>
</html>

上面的代码第一次运行,计算属性newStr的依赖值并没有发生改变,却触发了相应的函数,由<p><span>{{newStr}}</span></p>显示了结果,这是为什么?原因是:

  • new Vue()的时候,vue\src\core\instance\index.js里面的_init()初始化各个功能
function Vue (options) {
if (process.env.NODE_ENV !== 'production' &&
  !(this instanceof Vue)
) {
  warn('Vue is a constructor and should be called with the `new` keyword')
}
this._init(options) //初始化各个功能
}
  • _init()中有这样的一个执行顺序:其中initState()是在beforeCreatecreated之间
  initLifecycle(vm)
  initEvents(vm)
  initRender(vm)
  callHook(vm, 'beforeCreate')
  initInjections(vm) // resolve injections before data/props
  initState(vm) //初始化
  initProvide(vm) // resolve provide after data/props
  callHook(vm, 'created') 
  • 在initState()做了这些事情:
if (opts.props) initProps(vm, opts.props)//初始化Props
if (opts.methods) initMethods(vm, opts.methods)//初始化methods
if (opts.data) {
  initData(vm)} else {
  observe(vm._data = {}, true /* asRootData */)}//初始化data
if (opts.computed) initComputed(vm, opts.computed)//初始化computed
  • 所以Propsmethods,datacomputed的初始化都是在beforeCreatedcreated之间完成的。

十六.watch与computed的区别

共同点:

watch和computed都是以Vue的依赖追踪机制为基础的,它们都试图处理这样一件事情:当某一个数据(称它为依赖数据)发生变化的时候,所有依赖这个数据的“相关”数据“自动”发生变化,也就是自动调用相关的函数去实现数据的变动。

不同点:

1.watch监控属性依赖的值是单个,computed计算属性依赖的值是多个

2.watch没有缓存,computed提供缓存