Vue基础

一.初始Vue

首先创建一个简单的hello word项目

<!-- 准备好一个容器 -->
<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>

总结:

  1. 想让Vue工作,就必须创建一个Vue实例,且要传入一个配置对象;
  2. root容器里的代码依然符合html规范,只不过混入了一些特殊的Vue语法;
  3. root容器里的代码被称为【Vue模板】;
  4. Vue实例和容器是一一对应的;
  5. 真实开发中只有一个Vue实例,并且会配合着组件一起使用;
  6. {{xxx}}中的xxx要写js表达式,且xxx可以自动读取到data中的所有属性;
  7. 一旦data中的数据发生改变,那么页面中用到该数据的地方也会自动更新;

二.Vue模板语法

Vue模板语法有2大类:
	1.插值语法:
		功能:用于解析标签体内容。
		写法:{{xxx}},xxx是js表达式,且可以直接读取到data中的所有属性。
	2.指令语法:
		功能:用于解析标签(包括:标签属性、标签体内容、绑定事件.....)。
		举例:v-bind:href="xxx" 或  简写为 :href="xxx",xxx同样要写js表达式,
			且可以直接读取到data中的所有属性。
		备注:Vue中有很多的指令,且形式都是:v-????,此处我们只是拿v-bind举个例子。

三.Vue数据绑定

Vue中有2种数据绑定的方式:
	1.单向绑定(v-bind):数据只能从data流向页面。
	2.双向绑定(v-model):数据不仅能从data流向页面,还可以从页面流向data。
备注:
	1.双向绑定一般都应用在表单类元素上(如:input、select等)
	2.v-model:value 可以简写为 v-model,因为v-model默认收集的就是value值。

四.el和data的2种写法

  1.  el的两张写法
    • 在Vue实例中使用el绑定
    • 先创建Vue实例, 随后再通过vm.$mount('#root')指定el的值
<div id="root">
	<h1>你好,{{name}}</h1>
</div>

<script type="text/javascript">
Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。

//el的两种写法
const vue = new Vue({
//第一种写法
el:'#root',
data:{
	name:'尚硅谷'
	}
})

//第二种写法
v.$mount('#root')

    2. data的2种写法

    • 对象式
    • 函数式
//data的两种写法
new Vue({
	el:'#root',
//data的第一种写法:对象式
	data:{
		name:'尚硅谷'
		}

//data的第二种写法:函数式
	data(){
		return{
			name:'尚硅谷'
			}
		}
	})

注意 : 推荐使用第二种写法

五.Vue中的MVVM模型

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

总结:
	1.data中所有的属性,最后都出现在了vm身上。
	2.vm身上所有的属性 及 Vue原型上所有属性,在Vue模板中都可以直接使用。

六.数据代理

1.数据代理:通过一个对象代理对另一个对象中属性的操作(读/写)

<script type="text/javascript" >
	let obj = {x:100}
	let obj2 = {y:200}
	//通过defineProperty方法, 
	Object.defineProperty(obj2,'x',{
		get(){
			return obj.x
		},
		set(value){
			obj.x = value
		}
	})
	obj2.x=300
	console.log(obj.x) //结果是300
</script>

2.Vue中的数据代理

1.Vue中的数据代理:
         通过vm对象来代理data对象中属性的操作(读/写)
2.Vue中数据代理的好处:
         更加方便的操作data中的数据
3.基本原理:
         通过Object.defineProperty()把data对象中所有属性添加到vm上。
         为每一个添加到vm上的属性,都指定一个getter/setter。
         在getter/setter内部去操作(读/写)data中对应的属性。

七.事件处理

1.事件的基本使用:

  1. 使用v-on:事件名或 @事件名 绑定事件;
  2. 事件的回调需要配置在methods对象中,最终会在Vue实例上;
  3. methods中配置的函数,不要用箭头函数!否则函数里面的this就不是Vue实例了;
  4. methods中配置的函数,都是被Vue所管理的函数,this的指向是Vue实例 或 组件实例对象;
  5. @click="demo" 和 @click="demo()" 效果一致,但后者可以传参;
  6. @click="demo"和@click="stopRun($event)", 都可以在函数体中拿到event对象 ; 
<div id="root">
  <h2>欢迎来到{{name}}学习</h2>
  <button @click="showInfo1">点我提示信息1(不传参)</button>
  <button @click="showInfo2($event,66)">点我提示信息2(传参)</button>
</div>

<script type="text/javascript">
	Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。

	const vm = new Vue({
		el:'#root',
		data:{
			name:'尚硅谷',
			},
		methods:{
			showInfo1(event){
				// console.log(event.target.innerText)
				// console.log(this) //此处的this是vm
				alert('同学你好!')
			},
			showInfo2(event,number){
				console.log(event,number)
				// console.log(event.target.innerText)
				// console.log(this) //此处的this是vm
				alert('同学你好!!')
			}
		}
	})
</script>
<div id="root">
  <button type="button" @click="starRun">不传参</button>
  <button type="button" @click="stopRun($event)">传参</button>
  </div>
<script>
  //创建vue实例
  new Vue({
  el:'#root',
  data(){
    return{
        }
   },methods:{
       starRun(event){
       console.log(event.target)
       },
       stopRun(event){
          console.log(event.target)
        },
       }
   })
</script>

2.事件修饰符

  1. prevent:阻止默认事件(常用);
  2. stop:阻止事件冒泡(常用);
  3. once:事件只触发一次(常用);
  4. capture:使用事件的捕获模式;
  5. self:只有event.target是当前操作的元素时才触发事件;
  6. passive:事件的默认行为立即执行,无需等待事件回调执行完毕;
<!-- 准备好一个容器-->
<div id="root">
  <h2>欢迎来到{{name}}学习</h2>
  <!-- 阻止默认事件(常用) -->
  <a href="http://www.atguigu.com" @click.prevent="showInfo">点我提示信息</a>

  <!-- 阻止事件冒泡(常用) -->
  <div class="demo1" @click="showInfo">
	<button @click.stop="showInfo">点我提示信息</button>
	<!-- 修饰符可以连续写 -->
	<!-- <a href="http://www.atguigu.com" @click.prevent.stop="showInfo">点我提示信息</a> -->
  </div>

  <!-- 事件只触发一次(常用) -->
  <button @click.once="showInfo">点我提示信息</button>

  <!-- 使用事件的捕获模式 -->
  <div class="box1" @click.capture="showMsg(1)">
	div1
  <div class="box2" @click="showMsg(2)">
	div2
  </div>

  <!-- 只有event.target是当前操作的元素时才触发事件; -->
  <div class="demo1" @click.self="showInfo">
    <button @click="showInfo">点我提示信息</button>
  </div>

  <!-- 事件的默认行为立即执行,无需等待事件回调执行完毕; -->
  <ul @wheel.passive="demo" class="list">
    <li>1</li>
    <li>2</li>
    <li>3</li>
    <li>4</li>
  </ul>
</div>

<script type="text/javascript">
  Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。
  new Vue({
	el:'#root',
	data:{
	  name:'尚硅谷'
	},
	methods:{
	  showInfo(e){
		alert('同学你好!')
	  },
	  showMsg(msg){
		console.log(msg)
	  },
	  demo(){
		for (let i = 0; i < 100000; i++) {
		  console.log('#')
		}
		console.log('累坏了')
		}
	  }
  })
</script>

3.键盘事件

  1. Vue中常用的按键别名:          
    • 回车 => enter          
    • 删除 => delete (捕获“删除”和“退格”键)          
    • 退出 => esc          空格 => space        
    •  换行 => tab (特殊,必须配合keydown去使用)          
    • 上 => up          
    • 下 => down          
    • 左 => left          
    • 右 => right
  2. Vue未提供别名的按键,可以使用按键原始的key值去绑定,但注意要转为kebab-case(短横线命名)
  3. 系统修饰键(用法特殊):ctrl、alt、shift、meta          
    • 配合keyup使用:按下修饰键的同时,再按下其他键,随后释放其他键,事件才被触发。        
    • 配合keydown使用:正常触发事件。
  4. 也可以使用keyCode去指定具体的按键(不推荐)
  5. Vue.config.keyCodes.自定义键名 = 键码,可以去定制按键别名
<div id="root">
  <h2>欢迎来到{{name}}学习</h2>
  <input type="text" placeholder="按下回车提示输入" @keydown.huiche="showInfo"> //如果不自定义别名, 可以使用系统自带的别名
</div>

<script type="text/javascript">
  Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。
  Vue.config.keyCodes.huiche = 13 //定义了一个别名按键

  new Vue({
    el:'#root',
    data:{
      name:'尚硅谷'
    },
    methods: {
      showInfo(e){
        // console.log(e.key,e.keyCode)
        console.log(e.target.value)
    }
  },
})
</script>

八.计算属性(computed)

  1. 定义:要用的属性不存在,要通过已有属性计算得来。      
  2. 原理:底层借助了Objcet.defineproperty方法提供的getter和setter。      
  3. get函数什么时候执行?                
    • 初次读取时会执行一次。                
    • 当依赖的数据发生改变时会被再次调用。      
  4. 优势:与methods实现相比,内部有缓存机制(复用),效率更高,调试方便。      
  5. 备注:            
    • 计算属性最终会出现在vm上,直接读取使用即可。            
    • 如果计算属性要被修改,那必须写set函数去响应修改,且set中要引起计算时依赖的数据发生改变。
<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/>
  <!-- 全名:<span>{{fullName}}</span> <br/><br/>
  全名:<span>{{fullName}}</span> <br/><br/>
  全名:<span>{{fullName}}</span> -->
</div>

<script type="text/javascript">
  Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。

  const vm = new Vue({
    el:'#root',
    data:{
      firstName:'张',
      lastName:'三',
      x:'你好'
    },
    computed:{
      fullName:{
        //get有什么作用?当有人读取fullName时,get就会被调用,且返回值就作为fullName的值
        //get什么时候调用?1.初次读取fullName时。2.所依赖的数据发生变化时。
        get(){
          console.log('get被调用了')
          // console.log(this) //此处的this是vm
          return this.firstName + '-' + this.lastName
        },
        //set什么时候调用? 当fullName被修改时。
        set(value){
          console.log('set',value)
          const arr = value.split('-')
          this.firstName = arr[0]
          this.lastName = arr[1]
        }
      }
    }
  })
</script>
  
//简写
computed:{
  fullName(){
    console.log('get被调用了')
    return this.firstName + '-' + this.lastName
  }
}

九.监听属性(watch)

1.基础用法

  1. 当被监听的属性变化时, 回调函数自动调用, 进行相关操作
  2. 监听的属性必须存在,才能进行监视!!
  3. 监听的两种写法:
    • new Vue时传入watch配置
    • 通过vm.$watch绑定监听
<div id="root">
  <h2>今天天气很{{info}}</h2>
  <button @click="changeWeather">切换天气</button>
</div>

<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)
	    }
      }
	}
})
//监视属性写法二
vm.$watch('isHot',{
  immediate:true, //初始化时让handler调用一下
  //handler什么时候调用?当isHot发生改变时。
  handler(newValue,oldValue){
    console.log('isHot被修改了',newValue,oldValue)
  }
})
</script>

2.深度监听

  1. 深度监听
    • Vue中的watch默认不监测对象内部值的改变(一层)
    • 配置deep:true可以监测对象内部值改变(多层)。
  2. 备注:
    • Vue自身可以监测对象内部值的改变,但Vue提供的watch默认不可以! 
    • 使用watch时根据数据的具体结构,决定是否采用深度监视。
<div id="root">
        <input type="text" v-model="demo.num1">
        <select v-model="demo.cal">
            <option value="+">+</option>
            <option value="-">-</option>
            <option value="*">*</option>
            <option value="/">/</option>
        </select>
        <input type="text" v-model="demo.num2"><br/>
        <span>结果为:{{demo.res}}</span>

    </div>
    <script>
        //创建vue实例
        new Vue({
            el:'#root',
            data(){
                return{
                    demo:{
                        num1:0,
                        num2:0,
                        cal:"+",
                        res:0
                    }
                }
            },watch:{
                demo:{
                    deep:true, //设置深度监听, 监听的对象内部任意属性值发送变化, 均衡触发该方法
                    handler(newVal,oldVal) {
                        let res;
                        switch (newVal.cal){
                            case "+":
                                res = parseInt(newVal.num1)+parseInt(newVal.num2);
                                break;
                            case "-":
                                res = newVal.num1-newVal.num2;
                                break;
                            case "*":
                                res = newVal.num1*newVal.num2;
                                break;
                            case "/":
                                res = newVal.num1/newVal.num2;
                                break;
                        }
                        newVal.res =  res;
                    }
                }
            }
        })

    </script>

十.样式绑定

  1. class样式                
    • 写法:class="xxx" xxx可以是字符串、对象、数组。
    • 字符串写法适用于:类名不确定,要动态获取。
    • 对象写法适用于:要绑定多个样式,个数不确定,名字也不确定。
    • 数组写法适用于:要绑定多个样式,个数确定,名字也确定,但不确定用不用。
  2. style样式 
    • :style="{fontSize: xxx}"其中xxx是动态值。
    • :style="[a,b]"其中a、b是样式对象。
<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>
	</body>

	<script type="text/javascript">
		Vue.config.productionTip = false
		
		const vm = new Vue({
			el:'#root',
			data:{
				name:'尚硅谷',
				mood:'normal',
				classArr:['atguigu1','atguigu2','atguigu3'],
				classObj:{
					atguigu1:false,
					atguigu2:false,
				},
				styleObj:{
					fontSize: '40px',
					color:'red',
				},
				styleObj2:{
					backgroundColor:'orange'
				},
				styleArr:[
					{
						fontSize: '40px',
						color:'blue',
					},
					{
						backgroundColor:'gray'
					}
				]
			},
			methods: {
				changeMood(){
					const arr = ['happy','sad','normal']
					const index = Math.floor(Math.random()*3)
					this.mood = arr[index]
				}
			},
		})
	</script>

十一.条件渲染

  1. v-if          
    • 写法:                
      • v-if="表达式"                 
      • v-else-if="表达式"                
      • v-else="表达式"        
    • 适用于:切换频率较低的场景。          
    • 特点:不展示的DOM元素直接被移除。          
    • 注意:v-if可以和:v-else-if、v-else一起使用,但要求结构不能被“打断”。
  2. v-show          
    • 写法:v-show="表达式"          
    • 适用于:切换频率较高的场景。          
    • 特点:不展示的DOM元素未被移除,仅仅是使用样式隐藏掉    
  3. 备注
    • 使用v-if的时,元素可能无法获取到,而使用v-show一定可以获取到。
    • v-show是不符合条件是隐藏标签, v-if不符合条件是不加载标签
    • template标签不会改好dom结构, 涉及到多个重复判断, 可以结合v-if使用
<div id="root">
			<h2>当前的n值是:{{n}}</h2>
			<button @click="n++">点我n+1</button>
			<!-- 使用v-show做条件渲染 -->
			 <h2 v-show="false">欢迎来到{{name}}</h2> 
			 <h2 v-show="1 === 1">欢迎来到{{name}}</h2> 

			<!-- 使用v-if做条件渲染 -->
			 <h2 v-if="false">欢迎来到{{name}}</h2> 
			 <h2 v-if="1 === 1">欢迎来到{{name}}</h2> 

			<!-- v-else和v-else-if -->
			<div v-if="n === 1">Angular</div>
			<div v-else-if="n === 2">React</div>
			<div v-else-if="n === 3">Vue</div>
			<div v-else>哈哈</div> 

			<!-- v-if与template的配合使用 -->
			<template v-if="n === 1">
				<h2>你好</h2>
				<h2>尚硅谷</h2>
				<h2>北京</h2>
			</template>

		</div>
	</body>

	<script type="text/javascript">
		Vue.config.productionTip = false

		const vm = new Vue({
			el:'#root',
			data:{
				name:'尚硅谷',
				n:0
			}
		})
	</script>

十二.列表渲染

1.v-for指令:      

  1. 用于展示列表数据      
  2. 语法:v-for="(item, index) in xxx" :key="yyy"      
  3. 可遍历:数组、对象、字符串(用的很少)、指定次数(用的很少)
<div id="root">
			<!-- 遍历数组 -->
			<h2>人员列表(遍历数组)</h2>
			<ul>
				<li v-for="(p,index) of persons" :key="index">
					{{p.name}}-{{p.age}}
				</li>
			</ul>
		</div>

		<script type="text/javascript">
			Vue.config.productionTip = false
			
			new Vue({
				el:'#root',
				data:{
					persons:[
						{id:'001',name:'张三',age:18},
						{id:'002',name:'李四',age:19},
						{id:'003',name:'王五',age:20}
					]
				}
			})
		</script>

2.key的原理

  1. 虚拟DOM中key的作用:
    • key是虚拟DOM对象的标识,当数据发生变化时,Vue会根据【新数据】生成【新的虚拟DOM】,  随后Vue进行【新虚拟DOM】与【旧虚拟DOM】的差异比较              
  2. 对比规则:          
    • 旧虚拟DOM中找到了与新虚拟DOM相同的key:                  
      • 若虚拟DOM中内容没变, 直接使用之前的真实DOM!                  
      • 若虚拟DOM中内容变了, 则生成新的真实DOM,随后替换掉页面中之前的真实DOM。          
    • 旧虚拟DOM中未找到与新虚拟DOM相同的key创建新的真实DOM,随后渲染到到页面。                   
  3. 用index作为key可能会引发的问题:                
    • 若对数据进行:逆序添加、逆序删除等破坏顺序操作:  会产生没有必要的真实DOM更新 ==> 界面效果没问题, 但效率低。                
    • 如果结构中还包含输入类的DOM: 会产生错误DOM更新 ==> 界面有问题。
  4. 开发中如何选择key?:                
    • 最好使用每条数据的唯一标识作为key, 比如id、手机号、身份证号、学号等唯一值。              
    • 如果不存在对数据的逆序添加、逆序删除等破坏顺序操作,仅用于渲染列表用于展示,使用index作为key是没有问题的。
<div id="root">
	<!-- 遍历数组 -->
	<h2>人员列表(遍历数组)</h2>
	<button @click.once="add">添加一个老刘</button>
	<ul>
		<li v-for="(p,index) of persons" :key="index">
			{{p.name}}-{{p.age}}
			<input type="text">
		</li>
	</ul>
</div>

<script type="text/javascript">
	Vue.config.productionTip = false
			
	new Vue({
		el:'#root',
		data:{
			persons:[
				{id:'001',name:'张三',age:18},
				{id:'002',name:'李四',age:19},
				{id:'003',name:'王五',age:20}
					]
			},
		methods: {
			add(){
				const p = {id:'004',name:'老刘',age:40}
				this.persons.unshift(p)
				}
			},
		})
</script>

3.Vue监视数据原理

  1. vue会监视data中所有层次的数据。
  2. 如何监测对象中的数据?            
    • 通过setter实现监视,且要在new Vue时就传入要监测的数据。                
      • 对象中后追加的属性,Vue默认不做响应式处理              
      • 如需给后添加的属性做响应式,请使用如下API:Vue.set(target,propertyName/index,value) 或vm.$set(target,propertyName/index,value)
  3. 如何监测数组中的数据?                
    • 通过包裹数组更新元素的方法实现,本质就是做了两件事:                  
      • 调用原生对应的方法对数组进行更新。                  
      • 重新解析模板,进而更新页面。
  4. 在Vue修改数组中的某个元素一定要用如下方法:          
    • 使用这些API:push()、pop()、shift()、unshift()、splice()、sort()、reverse()          
    • Vue.set() 或 vm.$set()
  5. 特别注意:Vue.set() 和 vm.$set() 不能给vm 或 vm的根数据对象 添加属性!!!

十三.获取表单数据

  1. 若:<input type="text"/>,则v-model收集的是value值,用户输入的就是value值。
  2. 若:<input type="radio"/>,则v-model收集的是value值,且要给标签配置value值。
  3. 若:<input type="checkbox"/>      
    • 没有配置input的value属性,那么收集的就是checked(勾选 or 未勾选,是布尔值)      
    • 配置input的value属性:            
      • v-model的初始值是非数组,那么收集的就是checked(勾选 or 未勾选,是布尔值)            
      • v-model的初始值是数组,那么收集的的就是value组成的数组
  4. 备注:v-model的三个修饰符:            
    • lazy:失去焦点再收集数据            
    • number:输入字符串转为有效的数字            
    • trim:输入首尾空格过滤
<p>
  <input type="radio" name="sex" v-model="$parent.user.sex" value="1"
         :checked="$parent.user.sex == 1">男
  <input type="radio" name="sex" v-model="$parent.user.sex" value="0"
         :checked="$parent.user.sex == 0">女
</p>

十四.过滤器

  1. 定义:
    • 对要显示的数据进行特定格式化后再显示(适用于一些简单逻辑的处理)。
  2. 语法:      
    • 注册过滤器:Vue.filter(name,callback) 或 new Vue{filters:{}}      
    • 使用过滤器:{{ xxx | 过滤器名}}  或  v-bind:属性 = "xxx | 过滤器名"
  3. 备注:      
    • 过滤器也可以接收额外参数、多个过滤器也可以串联      
    • 并没有改变原本的数据, 是产生新的对应的数据
<div id="root">
  <h2>显示格式化后的时间</h2>
  <!-- 计算属性实现 -->
  <h3>现在是:{{fmtTime}}</h3>
  <!-- methods实现 -->
  <h3>现在是:{{getFmtTime()}}</h3>
  <!-- 过滤器实现 -->
  <h3>现在是:{{time | timeFormater}}</h3>
  <!-- 过滤器实现(传参) -->
  <h3>现在是:{{time | timeFormater('YYYY_MM_DD') | mySlice}}</h3>
  <h3 :x="msg | mySlice">尚硅谷</h3>
</div>

<div id="root2">
  <h2>{{msg | mySlice}}</h2>
</div>

<script type="text/javascript">
  Vue.config.productionTip = false
//全局过滤器
Vue.filter('mySlice',function(value){
  return value.slice(0,4)
})

new Vue({
  el:'#root',
  data:{
    time:1621561377603, //时间戳
    msg:'你好'
  },
  computed: {
    fmtTime(){
      return dayjs(this.time).format('YYYY年MM月DD日 HH:mm:ss')
    }
  },
  methods: {
    getFmtTime(){
      return dayjs(this.time).format('YYYY年MM月DD日 HH:mm:ss')
    }
  },
  //局部过滤器
  filters:{
    timeFormater(value,str='YYYY年MM月DD日 HH:mm:ss'){
      // console.log('@',value)
      return dayjs(value).format(str)
    }
  }
})

new Vue({
  el:'#root2',
  data:{
    msg:'hello,atguigu!'
  }
})
</script>

十五.Vue内置指令

  1. v-text指令:      
    • 作用:向其所在的节点中渲染文本内容。      
    • 与插值语法的区别:v-text会替换掉节点中的内容,{{xx}}则不会。
  2. v-html指令:      
    • 作用:向指定节点中渲染包含html结构的内容。      
    • 与插值语法的区别:                
      • v-html会替换掉节点中所有的内容,{{xx}}则不会。              
      • v-html可以识别html结构。      
    • 严重注意:v-html有安全性问题!!!!                
      • 在网站上动态渲染任意HTML是非常危险的,容易导致XSS攻击。
      • 一定要在可信的内容上使用v-html,永不要用在用户提交的内容上!
  3. v-cloak指令(没有值):
    • 本质是一个特殊属性,Vue实例创建完毕并接管容器后,会删掉v-cloak属性。
    • 使用css配合v-cloak可以解决网速慢时页面展示出{{xxx}}的问题。
  4. v-once指令:
    • v-once所在节点在初次动态渲染后,就视为静态内容了。
    • 以后数据的改变不会引起v-once所在结构的更新,可以用于优化性能。
  5. v-pre指令:
    • 跳过其所在节点的编译过程。
    • 可利用它跳过:没有使用指令语法、没有使用插值语法的节点,会加快编译。

十六.Vue生命周期

生命周期:
      1.又名:生命周期回调函数、生命周期函数、生命周期钩子。
      2.是什么:Vue在关键时刻帮我们调用的一些特殊名称的函数。
      3.生命周期函数的名字不可更改,但函数的具体内容是程序员根据需求编写的。
      4.生命周期函数中的this指向是vm 或 组件实例对象。
常用的生命周期钩子:
      1.mounted: 发送ajax请求、启动定时器、绑定自定义事件、订阅消息等【初始化操作】。
      2.beforeDestroy: 清除定时器、解绑自定义事件、取消订阅消息等【收尾工作】。

关于销毁Vue实例
      1.销毁后借助Vue开发者工具看不到任何信息。
      2.销毁后自定义事件会失效,但原生DOM事件依然有效。
      3.一般不会在beforeDestroy操作数据,因为即便操作数据,也不会再触发更新流程了。

十七.Vue组件

Vue中使用组件的三大步骤:
      一、定义组件(创建组件)
      二、注册组件
      三、使用组件(写组件标签)

一、如何定义一个组件?
         使用Vue.extend(options)创建,其中options和new Vue(options)时传入的那个options几乎一样,但也有点区别;
         区别如下:
               1.el不要写,为什么? ——— 最终所有的组件都要经过一个vm的管理,由vm中的el决定服务哪个容器。
               2.data必须写成函数,为什么? ———— 避免组件被复用时,数据存在引用关系。
         备注:使用template可以配置组件结构。

二、如何注册组件?
            1.局部注册:靠new Vue的时候传入components选项
            2.全局注册:靠Vue.component('组件名',组件)

三、编写组件标签:
            <school></school>
<div id="root">
  <hello></hello>
<hr>
  <h1>{{msg}}</h1>
<hr>
    <!-- 第三步:编写组件标签 -->
    <school></school>
<hr>
    <!-- 第三步:编写组件标签 -->
    <student></student>
</div>

<div id="root2">
  <hello></hello>
</div>

<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>`,
  // el:'#root', //组件定义时,一定不要写el配置项,因为最终所有的组件都要被一个vm管理,由vm决定服务于哪个容器。
  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)

//创建vm
new Vue({
  el:'#root',
  data:{
    msg:'你好啊!'
  },
  //第二步:注册组件(局部注册)
  components:{
    school,
    student
  }
})

new Vue({
  el:'#root2',
})
</script>
注意点:
      1.关于组件名:
               一个单词组成:
                        第一种写法(首字母小写):school
                        第二种写法(首字母大写):School
               多个单词组成:
                        第一种写法(kebab-case命名):my-school
                        第二种写法(CamelCase命名):MySchool (需要Vue脚手架支持)
               备注:
                     (1).组件名尽可能回避HTML中已有的元素名称,例如:h2、H2都不行。
                     (2).可以使用name配置项指定组件在开发者工具中呈现的名字。

      2.关于组件标签:
               第一种写法:<school></school>
               第二种写法:<school/>
               备注:不用使用脚手架时,<school/>会导致后续组件不能渲染。

      3.一个简写方式:
               const school = Vue.extend(options) 可简写为:const school = options
关于VueComponent:
         1.school组件本质是一个名为VueComponent的构造函数,且不是程序员定义的,是Vue.extend生成的。

         2.我们只需要写<school/>或<school></school>,Vue解析时会帮我们创建school组件的实例对象,
            即Vue帮我们执行的:new VueComponent(options)。

         3.特别注意:每次调用Vue.extend,返回的都是一个全新的VueComponent!!!!

         4.关于this指向:
               (1).组件配置中:
                        data函数、methods中的函数、watch中的函数、computed中的函数 它们的this均是【VueComponent实例对象】。
               (2).new Vue(options)配置中:
                        data函数、methods中的函数、watch中的函数、computed中的函数 它们的this均是【Vue实例对象】。

         5.VueComponent的实例对象,以后简称vc(也可称之为:组件实例对象)。
            Vue的实例对象,以后简称vm。
原文地址:https://www.cnblogs.com/japhi/p/15425784.html