赞
踩
一套用于构建用户界面的渐进式JavaScript框架
构建用户界面:vue负责将数据渲染到页面,不管数据的来源
渐进式:Vue可以自底向上逐层的应用简单应用:只需要一个轻量小巧的核心库(嵌入式)
复杂应用:可以引入各式各样的Vue插件
一个.vue文件就是一个组件,包含着html,css,js
.vue可以拿来用,想改结构、样式、交互可以直接在.vue文件中修改,不会影响其他组件的样式…,因为已经封装到这个.vue文件中了
举例说明:把数据放到ul中,以li的形式展现,达到 001-张三-18 的效果
//数据(persons)
[
{id:'001',name:'张三',age:18},
{id:'002',name:'李四',age:19},
{id:'003',name:'王五',age:20},
]
//容器
<ul id="list"></ul>
用js写(命令式编码)
//准备html字符串
let htmlStr = ''
//遍历数组拼接html字符串
persons.forEach( p => {
htmlStr += `<li>${p.id} - ${p.name} - ${p.age}</li>`
})
//获取list元素
let list = document.getElementById('list')
//修改内容(亲自操作DOM)
list.innerHTML = htmlStr
用vue写(声明式编码)
<ul id="list">
<li v-for="p in persons">
{{p.id}} - {{p.name}} - {{p.age}}
</li>
</ul>
ES6语法规范
ES6模块化
包管理器
原型、原型链
数组常用方法
axios
promise
经常用到,文档和API,还有各种组件,学习建议等等
.
src引入,安装vue浏览器插件(初学阶段)
1.表达式:一个表达式会产生一个值,可以放在任何一个需要值的地方:a、a+b、demo(1)、x === y ? ‘a’ : ‘b’
2.js代码(语句):1、if ( ) {} 2、for…
<div id="root">
<h1>Hello,{{name}}</h1> <!--插值符-->
</div>
<script>
// 创建Vue实例new Vue,并传入一个配置对象({})
new Vue({
//el用于指定当前Vue实例为哪个容器服务,值通常为css选择器字符串
el: '#root'
//data中用于存储数据,数据供el所指定的容器去使用,值我们暂时先写成一个对象
name:"张三"
})
</script>
Vue模板语法有两大类:
Vue中有2中数据绑定的方式:
备注:
1.双向绑定一般都应用在表单类元素上(如:input、select等)
2.v-model : value 可以简写为 v-model,因为v-model默认收集的就是value值
3.v-bind: 可以简写为 :
<body> <div id="root"> <h2>姓名:{{name}}</h2> <input :value="age"> <input v-model="age"> </div> </body> <script src="vue.js"></script> <script> new Vue({ // el:'#root', //对象式写法 data:{ name:'张三', age:'20' }, methods:{ isStudent(){ alert(`${this.name}是学生`) //此处的this是vm(vue实例对象),如果该方法使用箭头函数调用,this指向window } } }).$mount('#root') // 函数式写法 </script>
MVVM模型
观察发现:
let number = 18 let person = { name: '张三', sex: '男', } //添加一个新属性 Object.defineProperty(person,'age',{ value: 18, //控制属性是否可以枚举,默认值是false enumerable: true, //控制属性是否可以被修改,默认值是false configurable: true, //控制属性是否可以被删除,默认值是false // 当有人读取person的age属性时,get函数(getter)就会被调用,且返回值就是age的值 get:function(){ return number } //当有人修改person的age属性时,set函数(setter)就会被调用,且会收到修改的具体值 set(value){ //简写 console.log('有人修改了age属性,且值是',value) number = value } }) //遍历person对象中的属性名,用一个数组存放起来 console.log(Object.keys(person)) console.log(person)
数据代理:通过一个对象代理对另一个对象中属性的操作(读/写)
<div id='root'> <a href="www.xxx.com" @click.prevent="showInfo">点我提示信息</a> //修饰符可以连续写 <a href="http:www.atguigu.com" @click.prevent.stop="showInfo">点我提示信息</a> </div> <script> new Vue({ el:'#root', data:{ name:'张三' }, methods:{ showInfo(e){ alert("同学你好") } } }) </script>
keydown按下触发,keyup按下抬起触发
<input type="text" placeholder="按下回车提示输出" @keyup.ctrl.y="showInfo">
(1)初次读取时会执行一次
(2)当依赖的数据发生改变时会被再次调用
1.计算属性最终会出现在vm上,直接读取使用即可
2.如果计算属性要被修改,那必须写set函数去响应修改,且set中要引起计算时依赖的数据发生改变
<div id="root"> 姓:<input type="text" v-model="firstName"><br> 名:<input type="text" v-model="lastName"><br> 姓名:<span>{{fullName}}</span> </div> <script> new Vue({ el:'#root', data:{ firstName:'zhang', lastName:'san', }, computed:{ fullName:{ //get有什么作用?当有人读取fullName时,get就会被调用,且返回值就作为fullName的值 get(){ //此处的this是vm return this.firstName + '-' + this.lastName }, set(value){ const arr = value.split('-') //此时firstName发生改变,而fullName依赖的是firstName和lastName,所以fullName也会改变 this.firstName = arr[0] this.lastName = arr[1] } } } }) </script>
监视属性watch:
(1)new Vue时传入watch配置
(2)通过vm.$watch监视
(1)Vue中的watch默认不监测对象内部值的改变(一层)
(2)配置deep:true可以监测对象内部值改变(多层)
备注:
(1)Vue自身可以监测对象内部值的改变,但Vue提供的watch默认不可以
(2)使用watch时根据数据的具体结构,决定是否采用深度监视
<div id="root"> <h2>今天天气很{{info}}</h2> <button @click="changeWeather">切换天气</button> <h3>a的值是:{{numbers.a}}</h3> <button @click="numbers.a++">点我让a加1</button> </div> <script> new Vue({ el:'#root', data:{ isHot: true, numbers:{ a: 1 } }, computed:{ info() { return isHot ? '炎热' : '凉爽' } }, methods: { changeWeather() { this.isHot = !this.isHot } }, watch:{ isHot:{ //初始化时让handler调用一下 immediate:true, //handler什么时候调用?当isHot发生改变时 handler(newValue,oldValue){ console.log('isHot被修改了',newValue,oldValue) } }, numbers:{ deep:true, handler(){ console.log('numbers改变了') } } } }) </script> //写法二 /* vm.$watch('isHot',{ immediate:true, handler(newValue,oldValue){ console.log('isHot被修改了',newValue,oldValue) } }) */
computed和watch之间的区别:
两个重要的小原则:
绑定class样式 或 style样式
<div class="basic" :class="classObj">{{name}}</div><br>
<div class="basic" :style="styleObj">{{name}}</div>
data
classObj: {
atguigu1: true,
atguigu2: true,
},
styleObj: {
fontSize: '40px', //大驼峰写法,css的属性
color: 'red',
}
写法:
适用于: 切换频率较低的场景
特点:不展示的DOM元素直接被移除
注意:v-if可以和 :v-else-if、v-else一起使用,但要求结构不能被“打断”
写法:v-show=“表达式”
适用于:切换频率较高的场景
特点:不展示的DOM元素未被移除,仅仅是使用样式隐藏掉
注意:使用v-if的时候,元素可能无法获取到,而使用v-show一定可以获取到
//判断布尔值决定显示还是不显示
<div v-if="false">Angular</div>
<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-for指令:
<div id="root"> <!-- 遍历数组 --> <h2>人员列表</h2> <ul> //index数组下标 <li v-for="(p,index) of persons" :key="index"> {{p.name}}-{{p.age}} </li> </ul> </div> <script> new Vue({ el: "root", data: { persons: [ {id:'001',name:"张三",age:18}, {id:'002',name:"李四",age:19}, {id:'003',name:"王五",age:20}, ] } }) </script>
面试题:react、vue中的key有什么作用?(key的内部原理)
1.若虚拟DOM中内容没变,直接使用之前的真实DOM
2.若虚拟DOM中内容变了,则生成新的真实DOM,随后替换掉页面中之前的真实DOM
(2)旧虚拟DOM中未找到与新虚拟DOM相同的key
创建新的真实DOM,随后渲染到页面
会产生没有必要的真实DOM更新===> 界面效果没问题,但效率低(顺序改变,之前有的结构也会重新创建)
(2)如果结构中还包含输入类的DOM
会产生错误DOM更新===> 界面有问题
需求:有如下数据,搜索冬,名字中带有冬的数据会显示出来
<div id="root"> <h2>人员列表</h2> <input type="text" placeholder="请输入名字" v-model="keyWord"> <ul> <li v-for="(p,index) of filePersons" :key="index"> {{p.name}}--{{p.age}}-{{p.sex}} </li> </ul> </div> <script> //用watch实现 /* new Vue({ el:"#root", data:{ keyWord:'', persons:[ {id:'001',name:"马冬梅",age:19,sex:'女'}, {id:'002',name:"周冬雨",age:20,sex:'女'}, {id:'003',name:"周杰伦",age:21,sex:'男'}, {id:'004',name:"温兆伦",age:22,sex:'男'}, ], //列表遍历的filePersons就是搜索后要显示的数据,初始未空 filePersons:[] }, watch:{ keyWord:{ immediate:true, handler(val){ //filter遍历数组,过滤(或检验)满足回调函数的值到数组persons中 this.filePersons = this.persons.filter((p)=>{ //indexOf为-1,说明没有满足的数据,这里即返回遍历到的满足的数据 return p.name.indexOf(val) !== -1 }) } } } }) */ // 用computed实现 new Vue({ el: "#root", data: { keyWord: '', persons: [ { id: '001', name: "马冬梅", age: 19, sex: '女' }, { id: '001', name: "周冬雨", age: 20, sex: '女' }, { id: '001', name: "周杰伦", age: 21, sex: '男' }, { id: '001', name: "温兆伦", age: 22, sex: '男' }, ], }, computed:{ filePersons(){ return this.persons.filter((p)=>{ return p.name.indexOf(this.keyWord) !== -1 }) } } }) </script>
<div id="root"> <h2>人员列表</h2> <input type="text" placeholder="请输入名字" v-model="keyWord"> <button @click="sortType = 2">年龄升序</button> <button @click="sortType = 1">年龄降序</button> <button @click="sortType = 0">原顺序</button> <ul> <li v-for="(p,index) of filePersons" :key="p.id"> {{p.name}}-{{p.age}}-{{p.sex}} </li> </ul> </div> <script> //用computed实现 new Vue({ el:"#root", data:{ keyWord:'', sortType:0, persons:[ { id: '001', name: "马冬梅", age: 19, sex: '女' }, { id: '001', name: "周冬雨", age: 20, sex: '女' }, { id: '001', name: "周杰伦", age: 21, sex: '男' }, { id: '001', name: "温兆伦", age: 22, sex: '男' }, ], computed:{ filePersons(){ //filter用于对数组的过滤,不会改变原数组,对数组中的元素是通过检测指定数组中符合条件的所有元素 const arr = this.persons.filter((p)=>{ return p.name.indexOf(this.keyWord) !== -1 }) //判断一下是否需要排序(为真就会进入if判断) //点击三个按钮中的任何一个,都会返回一个sortType,通过判断sortType的值进行升序或是降序的操作 if(this.sortType){ //数组排序sort方法,会改变原数组 arr.sort((p1,p2)=>{ return this.sortType === 1 ? p2.age-p1.age : p1.age-p2.age }) } return arr } }, //更新时存在的一个问题 methods:{ updatMei(){ //this.persons[0].name = '马老师' //奏效 //this,persons[0].age = 50 //奏效 //this.persons[0] = {id:'001',name:'马老师',age:50,sex:'男'} //不奏效 this.persons.splice(0,1,{id:'001',name:'马老师',age:50,sex:'男'}) //想要页面的改变,就得改变原数组,使用改变原数组的方法 } } } }) </script>
Vue监视数据的原理:
Vue.set(target,propertyName/index,value)或
vm.$set(target,propertyName/index,value)
给收集数据的标签配置一个v-model,然后当用户点击时会返回一个value值(或布尔值),将返回的值存储起来
收集表单数据:
若:<input type="text"/>, 则v-model收集的是value值,用户输入的就是value值。
若:<input type="radio" />, 则v-model收集的是value值,且要给标签配置value值。
若:<input type="checkbox" />
1.没有配置input的value属性,那么收集的就是checked(勾选 or 未勾选,是布尔值)
2.配置input的value属性:
(1)v-model的初始值是非数组,那么收集的就是checked(勾选 or 未勾选,是布尔值)
(2)v-model的初始值是数组,那么收集的就是value组成的数组
备注:v-model的三个修饰符:
lazy :失去焦点再收集数据
number:输入字符串转为有效的数字
trim:输入首尾空格过滤
处理数据,有局部和全局之分
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> <div id="root"> <h2>显示格式化后的时间</h2> <!-- 计算属性实现 --> <h3>现在是:{{fmtTime}}</h3> <!-- methods实现 --> <h3>现在是:{{getFmtTime}}</h3> <!-- 过滤器实现 --> <h3>现在是:{{time | timeFormater}}</h3> <!-- 过滤器实现(传参) --> <h3>现在是:{{time | timeFormater('YYYY_MM_DD') | mySlice}}</h3> </div> <script src="../js/vue.js"></script> <script src="../js/dayjs.min.js"></script> <script> // 全局过滤器 Vue.filter('mySlice',function(value){ return value.slice(0, 4) }) new Vue({ el: '#root', data: { time: 1621561377603, }, 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){ return dayjs(value).format('YYYY年MM月DD日 HH:mm:ss') }, } }) </script> </body> </html>
一、 v-text指令
<div>{{name}}</div>
<div v-text='name'></div>
二、v-html指令
<div v-html='str'><div>
<script>
new Vue({
el:'#root',
data:{
str:'<h3>你好啊</h3>'
}
})
</script>
三、v-cloak指令(没有value)
[v-cloak]{
display: none
}
//获取所有标签中含v-cloak的元素
四、v-once指令
五、v-pre指令
<div id="root">
<h2 v-pre>Vue其实很简单</h2>
<h2>当前的n值是:{{n}}</h2>
<button @click='n++'>点我n+1</button>
</div>
vue实例对象中的directives属性
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> <!-- 需求1:定义一个v-big指令,和v-text功能相似,但会把绑定的数值放大10倍 需求2:定义一个v-fbind指令,和v-bind功能类似,但可以让其所绑定的input元素默认获取焦点 自定义指令总结: 一、定义语法: (1)局部指令: new Vue({ new Vue({ directives:{指令名:配置对象} 或 directives:{指令名:回调函数} }) )} (2)全局指令: Vue.directive(指令名,配置对象) 或 Vue.directive(指令名,回调函数) 二、配置对象中常用的3个回调: (1)bind:指令与元素成功绑定时调用 (2)inserted:指令所在元素被插入页面时调用 (3)update:指令所在模板结构被重新解析时调用 三、备注: 1.指令定义时不加v-,但使用时要加v- 2.指令名如果是多个单词,要使用kebab-case命名方式,不要用camelCase命名 --> <div id="root"> <h2>当前的n值是:<span v-text="n"></span> </h2> <h2>放大10倍后的n值是:<span v-big="n"></span> </h2> <button @click="n++">点我n+1</button> <hr> <input type="text" v-bind:value="n"> </div> <script src="../js/vue.js"></script> <script> /* Vue.directive('fbind',{ // 指令与元素成功绑定时(一上来) bind(element, binding) { element.value = binding.value }, // 指令所在元素被插入页面时 inserted(element, binding) { element.focus() }, // 指令所在的模板被重新解析时 update(element, binding) { element.value = binding.value } }) */ new Vue({ el:'#root', data:{ n:1 }, directives:{ // big函数何时会被调用?1.指令与元素成功绑定时(一上来)2.指令所在的模板被重新解析时 big(element,binding){ console.log('big',this); //注意,此处的this是window element.innerText = binding.value * 10 }, fbind:{ // 指令与元素成功绑定时(一上来) bind(element, binding){ element.value = binding.value }, // 指令所在元素被插入页面时 inserted(element, binding){ element.focus() }, // 指令所在的模板被重新解析时 update(element, binding){ element.value = binding.value } } } }) </script> </body> </html>
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。