Vue基础知识(一)

目录

1. vue中的数据绑定

2. MVVM模型

3. 数据代理

4. 事件处理methods 

5. 计算属性Computed

6. 监视属性watch  

7. 条件渲染v-if和v-show 

8. 列表渲染 

9. 收集表单数据 

10. 过滤器

11. 内置指令 

12. 自定义指令

1. vue中的数据绑定

vue中有两种数据绑定的方式:

  • 单向数据绑定(v-bind):数据只能从data流向页面
  • 双向数据绑定(v-model):数据不仅能从data流向页面,也能从页面流向data
<body>
	<div id="root">
		单向数据绑定:<input type="text" :value="name"><br/>
		双向数据绑定:<input type="text" v-model="name"><br/>
	</div>
</body>
<script type="text/javascript">
	Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。
	new Vue({
		el:'#root',
		data:{
			name:'尚硅谷'
		}
	})
</script>

 在上面文本框中输入值,不会影响下面文本框的值,而在下面文本框中输入值,上面文本框的值也会跟着一起改变,即为双向数据绑定,页面上的name改变了,data中的name也随之改变。

2. MVVM模型

  • M:模型(Model),data中的数据
  • V:视图(View),模板代码
  • VM:视图模型(ViewModel),Vue实例
  • data中的所有属性,都会在vue实例(即vm)身上,vm身上的所有属性及Vue原型上的所有属性,在Vue模板中都可以直接使用。

3. 数据代理

  • Object.defineProperty()方式
    let number = 18
    let person = {
        name:'张三',
        sex:'男',
    }
    
    Object.defineProperty(person,'age',{
        // value:18,
        // enumerable:true, //控制属性是否可以枚举,默认值是false
        // writable:true, //控制属性是否可以被修改,默认值是false
        // configurable:true //控制属性是否可以被删除,默认值是false
        //当有人读取person的age属性时,get函数(getter)就会被调用,且返回值就是age的值
        get(){
            console.log('有人读取age属性了')
            return number
        },
        //当有人修改person的age属性时,set函数(setter)就会被调用,且会收到修改的具体值
        set(value){
            console.log('有人修改了age属性,且值是',value)
            number = value
        }
    })

        用Object.defineProperty()方法定义的属性,默认是不可枚举、不可修改、不可删除的。

  • 何为数据代理
    <!-- 数据代理:通过一个对象代理对另一个对象中属性的操作(读/写)-->
    <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>
  • Vue中的数据代理 (1) vm.name,实际读取的是data中的name,set vm.name时,data.name也会修改,即通过vm对象代理对data对象中属性的操作,即为数据代理; (2) vm.name的来源:首先创建vm的时候,就会把配置中data中的数据放一份在vm里面,名为_data。然后再把_data中的数据拿一份到vm中。(3) vm._data里面不仅有data配置里面的属性,还有相应属性的get和set方法,目的是为了vue能够实现响应式操作,使得vue能够监测到数据的改变,从而更新页面。 

4. 事件处理methods 

  • 事件的基本使用

    <body>
		<!-- 
			事件的基本使用:
			1.使用v-on:xxx 或 @xxx 绑定事件,其中xxx是事件名;
			2.事件的回调需要配置在methods对象中,最终会在vm上;
			3.methods中配置的函数,不要用箭头函数!否则this就不是vm了;
			4.methods中配置的函数,都是被Vue所管理的函数,this的指向是vm 或 组件实例对象;
			5.@click="demo" 和 @click="demo($event)" 效果一致,但后者可以传参;
		-->
		<div id="root">			
            <button @click="showInfo1">点我提示信息1(不传参)</button>
			<button @click="showInfo2($event,66)">点我提示信息2(传参)</button>
		</div>
	</body>
	<script type="text/javascript">
		Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。
		const vm = new Vue({
			el:'#root',
			data:{
				name:'尚硅谷',
			},
	        methods:{
			    showInfo1(event){
				    // console.log(event.target) --> <button>点我提示信息1(不传参)</button>
				    // console.log(this) //此处的this是vm
			    },
			    showInfo2(event,number){
			        console.log(event,number)
			    }
		    }
		})
	</script>
  •  事件修饰符 

  1. prevent:阻止默认事件(常用); 2. stop:阻止事件冒泡(常用);3. once:事件只触发一次(常用); 4. capture:使用事件的捕获模式; 5. self:只有event.target是当前操作的元素时才会触发;6. passive:事件的默认行为立即执行,无需等待事件回调执行完毕。

  • 键盘事件

5. 计算属性Computed

  • 计算属性的原理:底层借助Object.defineProperty()的getter和setter方法来实现;get函数的执行时机:1. 初次读取的时候会执行一次;2. 当依赖的数据改变时会再次执行。
  • 计算属性和methods方法的区别:计算属性内部有缓存机制,效率更高,调试方便。
  • 计算属性最终会出现在vm上,可以直接读取;如果计算属性要被修改,那必须写set函数去响应修改,且set中要引起计算时依赖的数据发生改变(即要想页面动态响应计算属性的改变,需要有set方法)
<body>
	<div id="root">
		全名:<span>{{fullName}}</span>
	</div>
</body>
<script type="text/javascript">
	Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。
	const vm = new Vue({
		el:'#root',
		data:{
			firstName:'张',
			lastName:'三'
		},
		computed:{
            //完整写法
			fullName:{
				//get有什么作用?当有人读取fullName时,get就会被调用,且返回值就作为fullName的值
				get(){
					console.log('get被调用了')
					// console.log(this) //此处的this是vm
					return this.firstName + '-' + this.lastName
				},
				//set什么时候调用? 当fullName被修改时。
				set(value){
					const arr = value.split('-')
					this.firstName = arr[0]
					this.lastName = arr[1]
				}
			}
            //简写
			//fullName(){
		    // 	return this.firstName + '-' + this.lastName
		    //}
		}
	})
</script>
  • 计算属性的简写只适用于不会修改计算属性值的时候,即不调用set方法的时候。 

6. 监视属性watch  

  •  当被监视的属性变化时,回调函数会自动调用,进行相关操作。且只有当监视的属性存在的时候,才能进行监视。
  • 监视的两种写法:1. new Vue时传入watch配置;2. 通过vm.$watch监视
    //写法1
    /* watch:{
    	isHot:{
    		immediate:true, //初始化时让handler调用一下
    		//handler什么时候调用?当isHot发生改变时。
    		handler(newValue,oldValue){
    			console.log('isHot被修改了',newValue,oldValue)
    		}
    	}
        //简写
    	/* isHot(newValue,oldValue){
    			console.log('isHot被修改了',newValue,oldValue,this)
    	} */
    } */
    
    //写法2
    vm.$watch('isHot',{
    	immediate:true, //初始化时让handler调用一下
    	//handler什么时候调用?当isHot发生改变时。
    	handler(newValue,oldValue){
    		console.log('isHot被修改了',newValue,oldValue)
    	}
    })
    //简写
    /* vm.$watch('isHot',(newValue,oldValue)=>{
        console.log('isHot被修改了',newValue,oldValue,this)
    }) */
  • computed和watch之间的区别:computed能完成的功能,watch都能完成;而watch能完成的功能,computed不一定能够完成,例如:watch可以进行异步操作
    watch:{
    	firstName(val){
    	    setTimeout(()=>{
    				console.log(this)
    				this.fullName = val + '-' + this.lastName
    		},1000);
    	}
    }
     
  • 注意点: 被Vue管理的函数,比如methods方法等最好写成普通函数,所有不被Vue所管理的函数(定时器的回调函数、ajax的回调函数、Promise的回调函数等)最好写成箭头函数,这样this的指向才是vm或组件实例对象

7. 条件渲染v-if和v-show 

  • v-if写法:v-if=“表达式”,v-else-if=“表达式”,v-else=“表达式” ;v-show写法:v-show=“表达式”
  • v-if和v-show的区别: 使用v-if时,不展示的DOM元素直接被移除,适用于切换频率较低的场景;而使用v-show时。不展示的DOM元素未被移除,仅仅是使用样式隐藏掉,适用于切换频率较高的场景。因此,使用v-if时,元素可能无法获取到,而使用v-show则一定可以获取到。

8. 列表渲染 

  • 基本使用:v-for="(item, index) in arr"
    <ul>
    	<li v-for="(p,index) of persons" :key="index">
    		{{p.name}}-{{p.age}}
    	</li>
    </ul>
  • 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是没有问题的

  • Vue监测数据改变的原理 
  1. vue会监视data中所有层次的数据。
  2. 如何监测对象中的数据变化:通过setter实现监视,且要在new Vue时就传入要监测的数据,调用set方法之后,就会重新解析模板,随后生成新的虚拟DOM。对象后追加的属性,Vue默认不做响应式处理,如果需要给后添加的属性做响应式,可以使用:Vue.set(target, propertyName, value)或者vm.$set(target, propertyName, value) 
  3. 如何监测数组中的数据变化:通过包裹数组更新元素的方法实现,本质是:(1)调用原生对应的方法对数组进行更新;(2)重新解析模板,进而更新页面。在vue中修改数组中的某个元素一定要使用如下方法:(1)API:push(),pop(),shift(),unshift(),splice(),sort(),reverse();(2)Vue.set()或vm.$set()
  4. 注:Vue.set()或vm.$set()不能给vm或vm的根数据对象添加属性。
    <script type="text/javascript">
    		Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。
    		const vm = new Vue({
    			el:'#root',
    			data:{
    				student:{
    					name:'tom',
    					age:18,
    					hobby:['抽烟','喝酒','烫头'],
    					friends:[
    						{name:'jerry',age:35},
    						{name:'tony',age:36}
    					]
    				}
    			},
    			methods: {
    				addSex(){
    					// Vue.set(this.student,'sex','男')
    					this.$set(this.student,'sex','男')
    				},
    			}
    		})
    </script>

9. 收集表单数据 

  • <input type="text "/>,则v-model收集的是value值,用户输入的就是value值;
  • <input type="radio"/>,则v-model收集的是value值,且要配置value值;
  • <input type="checkbox"/>
  1.  没有配置value属性,那么收集的就是checked(勾选 or 未勾选,是布尔值)
  2. 配置了value属性:(1)v-model的初始值是非数组,那么收集的就是checked(勾选 or 未勾选,是布尔值);(2)v-model的初始值是数组,那么收集的的就是value组成的数组。
  • v-model的修饰符: 
  1. lazy:失去焦点再收集数据
  2. number:输入字符串转为有效的数字
  3. trim:输入首尾空格过滤
    账号:<input type="text" v-model.trim="userInfo.account"> <br/><br/>
    密码:<input type="password" v-model="userInfo.password"> <br/><br/>
    年龄:<input type="number" v-model.number="userInfo.age"> <br/><br/>
    性别:
    男<input type="radio" name="sex" v-model="userInfo.sex" value="male">
    女<input type="radio" name="sex" v-model="userInfo.sex" value="female"> <br/><br/>
    爱好:
    学习<input type="checkbox" v-model="userInfo.hobby" value="study">
    打游戏<input type="checkbox" v-model="userInfo.hobby" value="game">
    吃饭<input type="checkbox" v-model="userInfo.hobby" value="eat">

10. 过滤器

  • 定义:对要显示的数据进行特定格式化后再显示(适用于一些简单逻辑的处理)。
  • 语法:注册过滤器:Vue.filter(name,callback) 或 new Vue{filters:{}};使用过滤器:{{ xxx | 过滤器名}}  或  v-bind:属性 = "xxx | 过滤器名"
  • 备注:过滤器也可以接收额外参数、多个过滤器也可以串联;过滤器并没有改变原本的数据, 是产生新的对应的数据。
    <body>
    		<div id="root">
    			<!-- 过滤器实现 -->
    			<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>
    	</body>
    	<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:'你好,尚硅谷'
    			},
    			//局部过滤器
    			filters:{
    				timeFormater(value,str='YYYY年MM月DD日 HH:mm:ss'){
    					return dayjs(value).format(str)
    				}
    			}
    		})
    		new Vue({
    			el:'#root2',
    			data:{
    				msg:'hello,atguigu!'
    			}
    		})
    	</script>

11. 内置指令 

  • v-text:向其所在的节点中渲染文本内容,与插值语法的区别:v-text会替换掉节点中的内容,而插值语法不会。语法:v-text="xxx"。
  • v-html:向指定节点中渲染包含html结构的内容,与插值语法的区别:(1).v-html会替换掉节点中所有的内容,{{xx}}则不会;(2).v-html可以识别html结构。v-html有安全性问题,在网站上动态渲染任意HTML是非常危险的,容易导致XSS攻击,一定要在可信的内容上使用v-html,不要用在用户提交的内容上。
  • v-cloak:没有值,是一个属性,在Vue实例创建完毕并接管容器后,就会删掉v-cloak属性,使用css配合v-cloak可以解决网速慢时页面展示出{{xxx}}的问题。
    <html>
    	<head>
    		<meta charset="UTF-8" />
    		<title>v-cloak指令</title>
    		<style>
    			[v-cloak]{
    				display:none;
    			}
    		</style>
    	</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">
    		Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。
    		new Vue({
    			el:'#root',
    			data:{
    				name:'尚硅谷'
    			}
    		})
    	</script>
    </html>
  •  v-once:v-once所在节点在初次动态渲染后,即被视为静态内容,以后数据的改变不会引起v-once所在结构的更新,可以用于优化性能。
  • v-pre:可跳过其所在节点的编译过程。可利用该指令跳过没有使用指令语法、没有使用插值语法的节点,会加快编译。

12. 自定义指令 

  • 语法一:回调函数式 new Vue({directives:{指令名:回调函数}})(局部指令);Vue.directive(指令名:回调函数)(全局指令)。调用时机:1. 指令与元素成功绑定时(一上来);2. 指令所在的模板被重新解析时。
    <h2>放大10倍后的n值是:<span v-big="n"></span> </h2>
    new Vue({
    	el:'#root',
    	data:{
    		name:'尚硅谷',
    		n:1
    	},
    	directives:{
    		big(element,binding){
    			console.log('big',this) //注意此处的this是window
    			element.innerText = binding.value * 10
    		},
    	}
    })
  •  语法二: 对象式 new Vue({directives:{指令名:配置对象}})(局部指令);Vue.directive(指令名:配置对象)(全局指令)
    <input type="text" v-fbind:value="n">
    new Vue({
    	el:'#root',
    	data:{
    		name:'尚硅谷',
    		n:1
    	},
    	directives:{
    		fbind:{
    			//指令与元素成功绑定时(一上来)
    			bind(element,binding){
    				element.value = binding.value
    			},
    			//指令所在元素被插入页面时
    			inserted(element,binding){
    				element.focus()
    			},
    			//指令所在的模板被重新解析时
    			update(element,binding){
    				element.value = binding.value
    			}
    		}
    	}
    })
    //定义全局指令
    /* Vue.directive('fbind',{
    	bind(element,binding){
    		element.value = binding.value
    	},
    	inserted(element,binding){
    		element.focus()
    	},
    	update(element,binding){
    		element.value = binding.value
    	}
    }) */
  • 备注: 1. 指令定义时不加v-,但使用时要加v-;2. 指令名如果是多个单词,要使用kebab-case命名方式,不要要camelCase命名。
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值