<script>
let obj = {
x: 100
};
let obj2 = {
y: 200
}
Object.defineProperty(obj2, 'x', {
//当有人访问obj2.x属性,调用get() getter函数,且返回obj.x的值
get() {
console.log('我跟随obj.x 的修改');
return obj.x
},
//当有人修改obj2.x属性,调用set() setter函数,且返回value的值
set(value) {
console.log('我修改了obj2.x的值,并返回给obj.x');
//obj.x = value;
}
})
1.2 Object.defineProperty()
- Object.defineProperty() 方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象
- 参数 Object.defineProperty(obj, prop, descriptor)
1.obj 要定义属性的对象
2.prop 要定义或修改的属性的名称
3.descriptor 要定义或修改的属性描述符(配置项) - 返回值 传递给方法的对象
<script>
let number = 18;
let person = {
name: '尚硅谷',
sex: '男',
//age: 18
}
//Object.defineProperty 向对象添加属性
// object 属性名 {value}
Object.defineProperty(person, 'age', {
//value: 18,
//enumerable: true, //控制属性是否可以被枚举(遍历),默认是false
//writable: true, //控制属性是否可以被修改,默认是false
//configurable: true, //控制属性是否可以被删除,默认是false
//当有人访问person.age属性,调用get() getter函数,且返回age的值
get: function() {
console.log('有人读取age属性了');
return number
},
//当有人修改person.age属性,调用set() setter函数,且返回value的值
set(value) {
console.log('有人要修改age的值,且值是' + value);
number = value;
}
})
/* for (let k in person) {
console.log(person[k]);
}*/
</script>
1.3vue中的数据代理
Vue实例化的时候vm_data = option.data
数据代理时 name adderss 代理 vm_data
1.Vue中的数据代理:
通过vm对象来代理data对象中属性的 *** 作(读/写)
2.Vue中数据代理的好处:
更加方便的 *** 作data中的数据
3.基本原理:
通过Object.defineProperty()把data对象中所有属性添加到vm上。
为每一个添加到vm上的属性,都指定一个getter/setter。
vm_data=option.data
<script>
Vue.config.productionTip = false;
const vm = new Vue({
el: '.root',
data: {
name: '尚硅谷',
adderss: '北京科技园'
},
});
</script>
2022.05.03-08点34分
2.事件处理- 使用v-on:xxx 或 @xxx 绑定事件,其中xxx是事件名
- 事件的回调需要配置在methods对象中,最终会在vm上
- methods中配置的函数,都是被Vue所管理的函数,this的指向是vm 或 组件实例对象
- 不写参数,默认传递的是event; showInfo2($event,66),此时第一个参数是事件对象,第二个用户自定义
<body>
<div class="root">
<!-- <button v-on:click="showInfo">点击我提示信息(不传参)</button>-->
<!-- 简写 -->
<button @click="showInfo">点我提示信息</button>
<!-- <button v-on:click="showInfo2($event,66)">点击我提示信息2</button> -->
<button @click="showInfo2($event,66)">点击我提示信息2(传参)</button>
</div>
<script>
Vue.config.productionTip = false;
const vm = new Vue({
el: '.root',
data: {
name: '',
},
//回调函数
methods: {
showInfo(event) {
alert('你好,vue');
},
showInfo2(event, number) {
console.log(number);
alert('你好,vue22');
},
}
});
</script>
Vue中的事件修饰符
prevent:阻止默认事件(常用)
stop:阻止事件冒泡(常用)
once:事件只触发一次(常用)
<body>
<div class="root">
<!-- 事件修饰符 -->
<!-- 1.阻止事件的默认行为 -->
<a href="www.baidu.com" @click.prevent="showInfo">点击我</a>
<!-- 2.阻止事件冒泡 -->
<div class="demo" @click="showInfo2">
<div class="demo1" @click.stop="showInfo2"></div>
</div>
<!-- 事件可以连写 -->
<!-- <div class="demo1" @click.prevent.stop="showInfo2"></div> -->
<!-- 3.事件只触发一次 -->
<button @click.once="showInfo3">点击我</button>
</div>
<script>
Vue.config.productionTip = false;
const vm = new Vue({
el: '.root',
data: {
name: '',
},
methods: {
showInfo() {
alert('阻止事件的默认行为');
},
showInfo2() {
alert('阻止事件冒泡');
},
showInfo3() {
alert('事件值触发一次');
}
}
});
</script>
</body>
键盘事件
<body>
<!-- 键盘事件语法糖:@keydown,@keyup
Vue中常用的按键别名:
回车 => enter
删除 => delete
退出 => esc
空格 => space
换行 => tab (特殊,必须配合keydown去使用)
@keydown.keycode(自定义配置按键 不推荐)
Vue.config.keyCodes.键名 = 键码,可以定制按键
可以组合按键enter.x 触发事件-->
<div class="root">
<label for="">欢迎来到{{name}}学习</label><br>
<input type="text" @keydown.enter="showInfo">
</div>
<script>
Vue.config.productionTip = false;
const vm = new Vue({
el: '.root',
data: {
name: '尚硅谷',
},
methods: {
showInfo(e) {
console.log(e.target.value);
}
}
});
</script>
</body>
3.计算属性
计算属性
定义: 要用的属性不存在, 要通过已有属性计算得来
原理: 底层借助了Objcet.defineProperty方法提供的getter和setter
get函数什么时候执行?(1).初次读取时会执行一次(2).当依赖的数据发生改变时会被再次调用
methods 每次读取都会调用一次,计算属性会把fullName缓存到内部,只要值不发生改变,就不会调用get
优势: 与methods实现相比, 内部有缓存机制( 复用), 效率更高, 调试方便
备注:
计算属性最终会出现在vm上, 直接读取使用即可
如果计算属性要被修改, 那必须写set函数去响应修改, 且set中要引起计算时依赖的数据发生改变
<body>
<div class="root">
姓:<input type="text" v-model:value='firstName'> <br> 名:
<input type="text" v-model="lastName"> <br> 姓名:
<!-- 插值语法实现姓名案例 -->
<!-- <span>{{firstName.slice(0,3)}}- {{lastName}}</span> -->
<!-- 用回调函数实现姓名案例 -->
<!-- 计算属性实现姓名案例 -->
<!-- vm.fullName.get()会报错,与methods中函数不同 -->
<span>{{fullName}}</span><br>
<!-- <span>{{fullName}}</span><br>
<span>{{fullName}}</span><br>
<span>{{fullName}}</span><br>
<span>{{fullName}}</span><br> -->
</div>
<script>
Vue.config.productionTip = false;
const vm = new Vue({
el: '.root',
data: {
firstName: '张',
lastName: '三',
},
/*methods: {
fullName() {
console.log('methods被调用了');
return this.firstName + '-' + this.lastName
}
}*/
//计算属性
// 定义: 要用的属性不存在, 要通过已有属性计算得来
// 原理: 底层借助了Objcet.defineProperty方法提供的getter和setter
// get函数什么时候执行?(1).初次读取时会执行一次(2).当依赖的数据发生改变时会被再次调用
// 优势: 与methods实现相比, 内部有缓存机制( 复用), 效率更高, 调试方便
// methods 每次读取都会调用一次,计算属性会把fullName缓存到内部,只要值不发生改变,就不会调用get
// 备注:
// 计算属性最终会出现在vm上, 直接读取使用即可
// 如果计算属性要被修改, 那必须写set函数去响应修改, 且set中要引起计算时依赖的数据发生改变
computed: {
fullName: {
get() {
console.log('get被调用了');
//此时this 经过vue处理指向vm
return this.firstName + '-' + this.lastName
},
//此时的参数是修改后的新值
set(value) {
console.log('set', value)
//split 按照间隔符- 将字符串分成两个数组
const arr = value.split('-')
this.firstName = arr[0]
this.lastName = arr[1]
}
}
}
});
</script>
</div>
</body>
4.监视属性
- 用计算属性实现的监视属性也可以实现
<body>
<div class="root">
<span>今天的天气好{{Info}}</span><br>
<button @click="changeWeather">点击切换天气</button>
</div>
<script>
Vue.config.productionTip = false;
const vm = new Vue({
el: '.root',
data: {
isHOT: true,
},
methods: {
changeWeather() {
this.isHOT = !this.isHOT;
//console.log(this.isHOT);
}
},
computed: {
Info() {
return this.isHOT ? '炎热' : '凉快'
}
},
//监视某一个属性值的变化 计算属性也可以监视
//handler什么时候调用?当isHot发生改变时。
watch: {
isHOT: {
//初始化时执行一次handler 默认值是false
immediate: true,
handler(newvalue, oldvalue) {
console.log(newvalue, oldvalue);
}
}
}
});
//监视属性的第二种写法 开始不确定监视的属性
/* vm.$watch('isHot', {
immediate: true,
handler(newvalue, oldvalue) {
console.log(newvalue, oldvalue);
}
})*/
</script>
5.绑定class样式
<style>
.basic {
width: 200px;
height: 100px;
border: 1px solid black;
}
.happy {
background-color: pink;
}
.sad {
background-color: green;
}
.normal {
background-color: blue;
}
.atguigu1 {
background-color: pink;
}
.atguigu2 {
border-radius: 30px;
}
.atguigu3 {
border: 10px solid skyblue;
}
</style>
</head>
<body>
<div class="root">
<!-- 绑定class样式--字符串写法,适用于class的类名不确定,需要动态指定 -->
<!-- <div class="basic" :class="mood" @click="changeMood">{{name}}</div><br><br> -->
<!-- 绑定class样式--数组写法,适用于:要绑定的样式个数不确定、名字也不确定 -->
<!-- 可以使用数组方法 arr.shift arr.push 增加或者删除样式 -->
<div class="basic" :class="moodArr">{{name}}</div><br><br>
<!-- 绑定class样式--对象写法,适用于:要绑定的样式个数确定、名字也确定,但要动态决定用不用 -->
<div class="basic" :class="moodObj">{{name}}</div><br><br>
</div>
<script>
Vue.config.productionTip = false;
const vm = new Vue({
el: '.root',
data: {
name: '尚硅谷',
mood: 'normal',
moodArr: ['atguigu1', 'atguigu2', 'atguigu3'],
moodObj: {
atguigu1: false,
atguigu2: false,
atguigu3: true
}
},
methods: {
changeMood() {
const MoodArr = ['happy', 'sad', 'normal'];
const index = Math.floor(Math.random() * 3);
console.log(index);
this.mood = this.MoodArr[index];
},
},
watch: {}
});
</script>
</body>
6.条件渲染
1.1 v-if
写法:
(1).v-if=“表达式”
(2).v-else-if=“表达式”
(3).v-else=“表达式”
-
适用于:切换频率较低的场景
-
特点:不展示的DOM元素直接被移除
-
注意:v-if可以和:v-else-if、v-else一起使用,但要求结构不能被“打断”
<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>
1.2 v-show
- 写法:v-show=“表达式”
- 适用于:切换频率较高的场景
- 特点:不展示的DOM元素未被移除,仅仅是使用样式隐藏掉(display:none)
<button @click="n++">点击让n++</button>
<button @click="n--">点击让n--</button>
<div class="test" v-show="n==2">欢迎来到{{name}}</div>
1.3 列表渲染
v-for指令
- 用于展示列表数据
- 语法:v-for=“(item, index) in xxx” :key=“yyy”
- 可遍历:数组、对象、字符串(用的很少)、指定次数(用的很少)
- v-for 的两个参数 一个是索引值 一个是索引号
<body>
<div class="root">
<!-- v-for 的两个参数 一个是索引值 一个是索引号 -->
<!-- 遍历数组 -->
<ul>{{name}}
<li v-for="(p,index) in persons" :key="index">{{p.name}}--{{index}}</li>
</ul>
<!-- 遍历对象 第一个参数是value 第二个是键码 key -->
<ul>
<li v-for="(car,key) in cars">{{key}}--{{car}}</li>
</ul>
</div>
<script>
Vue.config.productionTip = false;
const vm = new Vue({
el: '.root',
data: {
name: '人员列表',
persons: [{
name: '张三',
id: 001,
age: 18
}, {
name: '历史',
id: 002,
age: 19
}, {
name: '王五',
id: 003,
age: 20
}],
cars: {
name: '奥迪A8',
price: '70万',
color: '黑色'
},
str: 'hello'
},
methods: {},
watch: {}
});
</script>
</body>
虚拟DOM中key的作用
-
key是虚拟DOM对象的标识,当数据发生变化时,Vue会根据【新数据】生成【新的虚拟DOM】, 随后Vue进行【新虚拟DOM】与【旧虚拟DOM】的差异比较,比较规则如下:
-
旧虚拟DOM中找到了与新虚拟DOM相同的key:
-
①.若虚拟DOM中内容没变, 直接使用之前的真实DOM!
-
②.若虚拟DOM中内容变了, 则生成新的真实DOM,随后替换掉页面中之前的真实DOM。
-
旧虚拟DOM中未找到与新虚拟DOM相同的key
-
创建新的真实DOM,随后渲染到到页面。
-
若对数据进行:逆序添加、逆序删除等破坏顺序 *** 作:
-
会产生没有必要的真实DOM更新 ==> 界面效果没问题, 但效率低。
- `<!-- 准备好一个容器-->
<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>
初始数据
persons: [{ id: ‘001’, name: ‘张三’, age: 18 },
{ id: ‘002’, name: ‘李四’, age: 19 },
{ id: ‘003’, name: ‘王五’, age: 20 }
]
vue根据数据生成虚拟 DOM
初始虚拟 DOM
<li key='0'>张三-18<input type="text"></li>
<li key='1'>李四-19<input type="text"></li>
<li key='2'>王五-20<input type="text"></li>
将虚拟 DOM 转为 真实 DOM
this.persons.unshift({ id: ‘004’, name: ‘老刘’, age: 40 })
在 persons 数组最前面添加上 { id: ‘004’, name: ‘老刘’, age: 40 }
新数据:
persons: [ { id: ‘004’, name: ‘老刘’, age: 40 },
{ id: ‘001’, name: ‘张三’, age: 18 },
{ id: ‘002’, name: ‘李四’, age: 19 },
{ id: ‘003’, name: ‘王五’, age: 20 }
]
vue根据数据生成虚拟 DOM
新虚拟 DOM
<li key='0'>老刘-30<input type="text"></li>
<li key='1'>张三-18<input type="text"></li>
<li key='3'>李四-19<input type="text"></li>
<li key='4'>王五-20<input type="text"></li>
将虚拟 DOM 转为 真实 DOM
因为老刘被插到第一个,重刷了 key 的值,vue Diff 算法 根据 key 的值 判断 虚拟DOM 全部发生了改变,然后全部重新生成新的 真实 DOM。实际上,张三,李四,王五并没有发生更改,是可以直接复用之前的真实 DOM,而因为 key 的错乱,导致要全部重新生成,造成了性能的浪费。
最好使用每条数据的唯一标识作为key, 比如id、手机号、身份z号、学号等唯一值
如果不存在对数据的逆序添加、逆序删除等破坏顺序 *** 作,仅用于渲染列表用于展示,使用index作为key是没有问题的
2022-05-04-09点18分 7.获取表单元素的技巧
1.v-model默认收集的是value
2.没有配置input的value属性,那么收集的就是checked(勾选 or 未勾选,是布尔值)
3.男女信息收集标准做法 name=“sex”
4.多组checkbox收集,data用数组
v-model的三个修饰符
- trim 去掉首尾的空格
- lasy 失去焦点在收集数据
- number 收集到数据是数字类型的 一般与 < input type=“number”>搭配使用
<!-- v-model的三个修饰符
trim 去掉首尾的空格
lasy 失去焦点在收集数据
number 收集到数据是数字类型的 一般与<input type="number">搭配使用 -->
<body>
<div class="root">
<form action="" @submit.prevent="demo">
<!-- v-model 默认收集的value -->
<label>账号: <input type="text" v-model.trim="account"> </label><br><br>
<label>密码: <input type="password" v-model.trim="password"> </label><br><br>
<label>年龄: <input type="number" v-model.number="age"> </label><br><br>
<label>性别: 男:<input type="radio" name="sex" checked="checked" value="male" v-model="sex">
女:<input type="radio" name="sex" value="female" v-model="sex"></label><br><br>
<!-- 多组checkbox收集,data用数组 -->
<label>爱好: 吃饭:<input type="checkbox" checked="checked" value="eat" v-model="hobbies">
睡觉:<input type="checkbox" value="sleep" v-model="hobbies">
打豆豆:<input type="checkbox" value="beatDou" v-model="hobbies">
</label><br><br>
<!-- select收集数据在v-model绑定在select 不要写在option上 -->
<select name="" id="" v-model="schAddress">
<option value="" >请选择你的校区</option>
<option value="beijing" >北京</option>
<option value="shanghai" >上海</option>
<option value="guangzhou" >广州</option>
<option value="shenzhen" >深圳</option>
</select><br><br>
<label>其他信息: <textarea name="" id="input" class="form-control" rows="3" required="required" v-model.lazy="otherInfo">
</textarea></label><br><br>
<!-- 此时不需要input 的value -->
<input type="checkbox" v-model="agree"><span>阅读并接受 <a href="">《用户协议》</a></span><br><br>
<button>提交</button>
</form>
</div>
<script>
Vue.config.productionTip = false;
const vm = new Vue({
el: '.root',
data: {
account: '',
password: '',
age: '',
sex: '',
hobbies: [],
schAddress: '',
otherInfo: '',
agree: ''
},
methods: {
demo() {
console.log(JSON.stringify(this._data));
}
},
computed: {},
watch: {}
});
</script>
2022-5-5-09点46分
8.内置指令
- v-text
v-text指令:(使用的比较少)
1.作用:向其所在的节点中渲染文本内容。
2.与插值语法的区别:v-text会替换掉节点中的内容,{{xx}}则不会。
3.v-text 不会解析html标签
<div class="root">
<!-- v-text指令:(使用的比较少) -->
<!-- 1.作用:向其所在的节点中渲染文本内容。 -->
<!-- 2.与插值语法的区别:v-text会替换掉节点中的内容,{{xx}}则不会。 -->
<!-- 3.v-text 不会解析html标签 -->
<div>你好,{{name}}</div>
<div v-text="name">你好</div>
-
v-html
1.作用:向指定节点中渲染包含html结构的内容。 2.与插值语法的区别: v-html会替换掉节点中所有的内容,{{xx}}则不会。 v-html可以识别html结构。 3.严重注意:v-html有安全性问题!!!! 在网站上动态渲染任意HTML是非常危险的,容易导致XSS攻击。 一定要在可信的内容上使用v-html,永不要用在用户提交的内容上!
//此时会解析str中html标签
<div v-html="str">这是我原来的结构</div>
<script>
Vue.config.productionTip = false;
const vm = new Vue({
el: '.root',
data: {
n: 0,
name: '尚硅谷',
str: '这是一个html 的h2标签'
},
methods: {},
computed: {},
watch: {}
});
</script>
- v-once
1. v-once所在节点在初次动态渲染后,就视为静态内容了。
2. 以后数据的改变不会引起v-once所在结构的更新,可以用于优化性能
//此时div中 n的值是第一次的值
<div v-once>{{n}}</div>
<button @click="n++">点击我让n++---{{n}}</button>
- v-pre
v-pre指令:(比较没用)
跳过其所在节点的编译过程
可利用它跳过:没有使用指令语法、没有使用插值语法的节点,会加快编译
<div v-pre>我没有使用vue</div>
<div>{{name}}</div>
9.自定义指令
配置项关键词 directives
简写形式不能进行复杂的调用
<body>
<div class="root">
<div v-text="n"></div>
<!-- 自定义指令 使n数值放大十倍 -->
<div v-big="n"></div>
<button @click="n++">点击让n++</button><br>
<input type="text" v-fbind:value="n">
</div>
<script>
Vue.config.productionTip = false;
const vm = new Vue({
el: '.root',
data: {
n: 1,
name: '',
},
methods: {},
computed: {},
watch: {},
directives: {
//big 函数何时被调用? 1.指令和元素绑定时(一上来,此时元素在内存中,还没有渲染到页面上)
// 2.指令所在的模板重新解析时(值发生变化就会重新解析)
big(element, binding) {
//参数1 真实dom元素 参数2指令
//console.log(a, b);
element.innerText = binding.value * 10;
},
/*fbind(element, binding) {
//此时input第一次不能获得焦点
//点击一次input被放到html 才能获得焦点
element.value = binding.value;
element.focus();
// console.log(binding);
}*/
fbind: {
//1.指令和元素绑定时
bing(element, binding) {
element.value = binding.value;
console.log("bind");
},
//2.指令所在元素被插入页面时
inserted(element, binding) {
element.focus();
console.log('inserted');
},
//3.指令所在的模板被重新解析时
update(element, binding) {
element.value = binding.value;
console.log('update');
}
}
}
});
</script>
</body>
- 定义全局指令
Vue.directive('fbind', {
// 指令与元素成功绑定时(一上来)
bind(element, binding){
element.value = binding.value
},
// 指令所在元素被插入页面时
inserted(element, binding){
element.focus()
},
// 指令所在的模板被重新解析时
update(element, binding){
element.value = binding.value
}
})
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)