每天一点VUE(DAY 4-VUE2篇)

目录

1、修改数组的内容出现的问题

2、手写Vue检测数据的原理

3、Vue.set()和vue实例的$set()

4、操作数组的数据发生改变

5、v-model的表单获取,(细节满满)

6、filters过滤器的使用

7、5个不常用的内部指令

8、自定义指令


1、修改数组的内容出现的问题

点击第一个按钮,可以切换数组people的第0项的name属性,但是点击第二个按钮,修改people的整个第2项,发现页面上数据没变,我门在控制台输出people的第2项发现,数据是被修改了,但是页面没有渲染,说明Vue没有检测到数组数据的改变。

解决:看本节3和4

<div id="block">
	<div v-for="(item,index) in people" :key="item.id">
		{{item.name}}<br>
		{{item.age}}<br>
		-----------
	</div>
	<button type="button" @click="change001Name">点击切换001的名字</button>
	<button type="button" @click="change003">点击切换003整体</button>
</div>

<script type="text/javascript">
	Vue.config.productionTip = false;
	const vm = new Vue({
		el: '#block',
		data: {
			people: [
			{id: 0,name: '001',age: 30},
			{id: 1,name: '002',age: 20},
			{id: 2,name: '003',age: 40}]
		},
		methods:{
			change001Name(){
				this.people[0].name = "000"
			},
			change003(){
				this.people[2] = {id:3,name:"004",age:80}
			}
		}

	})
</script>

2、手写Vue检测数据的原理

/*这里的缺点是:
    1:没有做数据代理
    2:没有做深度的检测,如果对象里面有对象,或者对象里面的数组有对象
      就无法添加getter和setter
*/	
    var people =  {
		name:"potkiss",
		height:90,
		age:80,
		friend:{
			name:'kk'
		},
		family:[{name:'father'},{name:'mother'}]
	};
	let a = new Observe(people);
	let vm = {}
	vm._data = data = a
	console.log(vm)
	function Observe(re){
        //遍历构造函数的属性
		Object.keys(re).forEach((item,index)=>{
        //this指向的是实例对象,给这个this添加属性
			Object.defineProperty(this,item,{
				get(){
                    //这里可以像数组一样获取对象的值
					return re[item]
				},
				set(val){
					console.log(`${val}被改了,开始解析模版,生成虚拟dom,进行比较`)
					re[item] = val
				}
			})
		})
	}

3、Vue.set()和vue实例的$set()

        这样操作后的数据是可以被vue检测到的,是有getter和setter的,能后引发后面的一系列动作,
         缺点:不能在Vue下或者Vm根下添加数据

    /*这样操作后的数据是可以被vue检测到的,
    是有getter和setter的,能后引发后面的一系列动作,
    缺点:不能在Vue下或者Vm根下添加数据
    */	
    <div id="block">
			{{name}}<br>
			{{height}}<br>
			年龄:{{hobb.age}}<br>
			爱好<br>
			{{hobb.name}}<br>
			家人<br>
			<ul v-for="(item,index) in family" :key="index">
				<li>{{item.name}}</li>
			</ul>
		<button type="button" @click="change001">点击添加年龄值</button>
		<button type="button" @click="change002">点击添加家庭成员</button>
	</div>

	<script type="text/javascript">
	Vue.config.productionTip = false
	let vm = new Vue({
			el:'#block',
			data:{
				name:"potkiss",
				height:190,
				hobb:{
					name:'写代码',
				},
				family:[{name:'father'},{name:'mother'}]
			},
			methods:{
				change001(){
                    /*注意:Vue.set()和vm.$set()方法,
                        都无法在data或者Vm上直接添加数据,
                        只能在data或者vm上面的某一个对象上追加,
                        只有用set()方法追加的数据才可以被VUe检测到
                        才可以进行后面的解析模版,等一系列操作。
                    */
					 Vue.set(this.hobb,'age','99') //属于Vue上的方法
					this.$set(this.hobb,'age','99')    //属于Vm上的方法
				},
				change002(){
                    /*
                        第一个在数组的第二位置追加了一个元素
                        第二个吧数字的第一位替换了,
                        这样操作后的数组里面的对象是有getter和setter的
                        但是不建议这样做,操作数组我们可以用后面的7个常用
                        操作数字的方法。
                    */
					 Vue.set(this.family,2,{name:'potkiss'})  //属于Vue上的方法
					this.$set(this.family,0,{name:'potkiss'})  //属于Vm上的方法
				}
			}
			
		})
	</script>
	

4、操作数组的数据发生改变

(1)注意只有下面的这7个可以改变数组的顺序的方法才可以,像filter就不行,如果想用filter就吧过滤好的数组用7个方法替换即可。
        (2)这七个方法其实已经不是原本的Array上的方法了,而是Vue给重新打包分装好的,当我们使用这5个方法时,

(你可以在控制台输入这两条语句let a =[];vm.family.shift === b.shift;然后看结果是不是false)
           1、调用原本Array上的原本的方法,
           2、解析模版,生成虚拟DOM,diff对比,渲染。。。 

    /*
        (1)注意只有下面的这7个可以改变数组的顺序的方法才可以,
        像filter就不行,如果想用filter就吧过滤好的数组用
        下面的7个方法替换即可。
        
        (2)这七个方法其实已经不是原本的Array上的方法了,
(你可以在控制台输入这两条语句let a =[];vm.family.shift === b.shift;然后看结果是不是false)
        而是Vue给重新打包分装好的,当我们使用这5个方法时,
           1、调用原本Array上的原本的方法,
           2、解析模版,生成虚拟DOM,diff对比,渲染。。。 
        
    */    
    <div id="block">
		家人<br>
		<ul v-for="(item,index) in family" :key="index">
			<li>{{item.name}}</li>
		</ul>
		<button type="button" @click="change001">点击添加年龄值</button>
	</div>
	</body>
	<script type="text/javascript">
	Vue.config.productionTip = false
	let vm = new Vue({
			el:'#block',
			data:{
				family:[{name:'mother',age:20},{name:'father',age:80}]
			},
			methods:{
				change001(){
                     this.family.splice(0,2,{name:'potkiss'}) //替换数组的某长度元素,{第几位开始,到第几位,换成啥}
					 this.family.pop() //移除最后一个
					 this.family.push({name:'potkiss'}) //后面追加一个
					 this.family.shift() //删除第一个
					 this.family.unshift({name:'potkiss'}) //前面追加一个
					 this.family.sort(function(a,b){return b.age-a.age}) //排序,参数必须是一个函数,这里是由大到小排列
					 this.family.reverse() //翻转数组
				}
			}
		})
	</script>

5、v-model的表单获取,(细节满满)


	<!-- 这里给submit事件添加了一个阻止默认行为的属性 -->
	<form id="block" @submit.prevent="sub">
		<!-- 这里的trim是删除输入字符前后的空格 -->
		姓名:<input type="text" v-model.trim="UserInfo.name"><br>
		<!-- 这里的trim是删除输入字符前后的空格 -->
		密码:<input type="password" v-model.trim="UserInfo.password"><br>
		<!-- 这里type为number是为了让用户只可以输入数字,v-model后面的number是让用户输入的内容强制变为数字类型的数据 -->
		年龄:<input type="number" v-model.number="UserInfo.age"><br>
		性别:
		<!-- 这里的name可以让多个单选框只可以选中一个,但是要注意还要写一个value的值,才可以获取到,不然获取到的就是空字符串 -->
		男<input type="radio" name="sex" value="male" v-model="UserInfo.sex">
		女<input type="radio" name="sex" value="female" v-model="UserInfo.sex"><br>
		爱好:
		<!-- 这里也是,一定要写value,不然v-model获取到的就是checked这个属性,又因为三个绑定了同一个字段,所以会同时操作三个 -->
		<!-- 还要注意下面的数据要是数组,不然就还是获取的checked这个属性的值 -->
		吃饭:<input type="checkbox" v-model="UserInfo.hobby"  value="eat">
		喝酒:<input type="checkbox" v-model="UserInfo.hobby" value="drink">
		抽烟:<input type="checkbox" v-model="UserInfo.hobby"  value="smoke"><br>
		地址:
		<!-- 注意这里要绑定在select上 -->
		<select v-model="UserInfo.address">
			<option value="" >选一个</option>
			<option  value="xj">新疆</option>
			<option  value="bj">北京</option>
			<option  value="lz">兰州</option>
		</select><br>
		<!-- 这里的lazy是当用户失去焦点后获取输入的值 -->
		<textarea  cols="30" rows="10" v-model.lazy="UserInfo.text"></textarea><br>
		<!-- 这里直接获取的checked的值 -->
		<input type="checkbox" v-model="UserInfo.check" >协议<br>
		<button>提交</button>
	</form>


<script type="text/javascript">
Vue.config.productionTip = false
let vm = new Vue({
		el:'#block',
		data:{
			UserInfo:{
				name:'',
				password:'',
				age:null,
				sex:'',
				hobby:[], //注意这个数据类型
				address:'',
				text:'',
				check:true
			}
		},
		methods:{
			sub(){
				//把所有数据放在一个对象里面就可以一次性获取,并且方便后面添加属性,因为Vue.set()不能再根上添加
				console.log(this.UserInfo);
			}
		}
	})
</script>

6、filters过滤器的使用

注意这里用了dayjs这个库

<script src="https://cdn.bootcdn.net/ajax/libs/dayjs/1.11.1/dayjs.min.js"></script>
<body>
		<div id="block">
			1: {{comTime}}<br>
			2: {{getTime()}}<br>
			3 {{time | filterTime("abc") | cutString | CutString}}<br>
			<div id="block2">
				<!-- 这里的cutString也可以用是因为block2包含在block1中的 -->
				4: {{time | filterTime("abc") | cutString }}<br>
				5: {{time | filterTime("abc") | CutString}}<br>
			</div>
		</div>
	</body>
	<script type="text/javascript">
	Vue.config.productionTip = false
	//全局的filter,别的组件也可以用
	Vue.filter('CutString',function(value){
		return value.slice(0,1);
	})
	let vm = new Vue({
			el:'#block',
			data:{
				time:'1650216828381'
			},
			methods:{
				getTime(){
					return dayjs(Date.now()).format('YY-MM-DD HH-MM-SS')
				}
			},
			computed:{
				comTime(){
					return dayjs(Date.now()).format('YY-MM-DD HH-MM-SS')
				}
			},
			filters:{
				filterTime(value,can){
					console.log(value,can)
					return dayjs(Date.now()).format('YY-MM-DD HH-MM-SS')
				},
				cutString(value){
					/*
						功能:只显示前4位,
						问题:别的Vue实例(组件)不能用
						解决:在实例前面弄全局的过滤器,注意,一次只能弄一个
					*/
					return value.slice(0,4);
				}
			}
		})
		let vm2 = new Vue({
			el:'#block2',
		})
	</script>

7、5个不常用的内部指令

v-text;v-html;v-cloak;v-once;v-pre

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8" />
		<title>内部指令</title>
	</head>
	<style>
		[v-cloak]{
			display: none;
		}
	</style>
	<body>
		<div id="block">
			<div>{{data}},world</div>
			<!-- v-text的特别的地方是会替换这个元素的全部文本,不能拼接 -->
			<div v-text="data">world</div>
			<!-- v-html可以解析有标签的结构,
				但是有危险,可能会被xss攻击,一般不建议用!!!,
				比如我写一个跳转的链接,通过这种可以解析
				html的地方输入出去,比如评论,当有人点击了我的评论
				然后会把点击的用户的本地没有HTTP-ONLY的cookie
				给截取到发给劫持者的服务器,然后劫持者接可以为所欲为了
			 -->
			<div v-html="data2"></div>
			<!--v-cloak这个属性是如果页面引入的js加载太慢了,
				没有渲染VUE时会出现,页面开始渲染了就消失了,
				可以配合css,实现在页面还没渲染之前隐藏动态元素
			-->
			<div v-cloak>{{data3}}</div>
			<!-- v-once指的是这个动态数据值渲染一次,渲染完就是静态数据了 -->
			<div v-once >初始值{{n}}</div>
			<div >{{n}}</div>
			<button @click="n++">点击++</button>
			<!-- 有v-pre的元素,vue在渲染页面时会跳过,加快渲染进度, -->
			<div v-pre>静态的数据</div>
		</div>
		<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
	</body>
	<script type="text/javascript">
	Vue.config.productionTip = false
	
	let vm = new Vue({
			el:'#block',
			data:{
				data:'hello',
				data2:'<h2>hello</h2>',
				data3:'potkiss',
				n:0
			}
		})
		
	</script>
</html>

8、自定义指令

注意:自定义指令在绑定时写的是v-xx;在自定义指令定义的地方写的xx;自定义指令的名字不能用驼峰命名,因为用了Vue就会把大写变成小写,也可以用短横杠连接如v-name-big;如果用了短杠,需要在directives里面的名字加引号如'name-big'

<body>
	<div id="block">
		<div v-text="n"></div>
		<input type="text" v-f-bind="n">
		<div v-big="n"></div>
	</div>
</body>
<script type="text/javascript">
Vue.config.productionTip = false;
//全局的自定义指令
//Vue.directive('name',{}或者function(){})
let vm = new Vue({
		el:'#block',
		data:{
			n:1,
		},
		directives:{
            //想实习一上来就获取焦点,所以要写出对象,只可以操作inserted方法
			"f-bind":{
				bind(element,binding){
					//当自定义指令和元素成功绑定时调用
					console.log(1);
					element.value = binding.value;
				},
				inserted(element,binding){
					//当绑定的元素被插入页面时调用
					console.log(2);
					element.focus();
				},
				update(element,binding){
					//指令所在的模版被重新解析时
					console.log(3);
					element.value = binding.value;
				}
			},
			big(element,binding){
				//写出函数的形式相当于没有调用inserted这个方法
				element.innerText = binding.value * 10
			}
		}
	})
	
</script>

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值