Vue
Vue概述
- Vue:渐进式JavaScript框架
- 声明式渲染 -> 组件系统 -> 客户端路由 -> 集中式状态管理 -> 项目构建
- 官网:https://cn.vuejs.org/v2/guide
- 易用 - 熟悉HTML、CSS、JavaScript知识后,可快速上手
- 灵活 - 在一个库和一套完整框架之间自如伸缩
- 高效 - 10kb运行大小,超快虚拟DOM
Vue基本使用
实际案例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Hello World</title>
</head>
<body>
<dir id="app">
<dir>{
{msg}}</dir>
<div>{
{1 + 2}}</div>
<div>{
{msg + '----' + 123}}</div>
</dir>
<script src="../vue.js"></script>
<script>
/*
Vue的基本使用步骤
1、需要提供标签用于填充数据
2、引入vue.js文件
3、可以使用vue的语法做功能了
4、把vue提供的数据填充到标签里面
*/
var vm = new Vue({
el:'#app',
data:{
msg:'Hello World'
}
})
</script>
</body>
</html>
- Vue的基本使用步骤
- 1、需要提供标签用于填充数据
- 引入vue.js文件
- 可以使用vue的语法做功能了
- 把vue提供的数据填充到标签里面
实例参数分析
-
el:元素的挂载位置(值可以是CSS选择器或者DOM元素)
-
data:模型数据(值是一个对象)
-
插值表达式用法
- 将数据填充到HTML标签中
- 插值表达式支持基本的计算操作
-
Vue代码运行原理分析
- 概述编译过程的概念(Vue语法 -> 原生语法)
- 概述编译过程的概念(Vue语法 -> 原生语法)
Vue模板语法
如何理解前端渲染
前端渲染方式
- 原生js拼接字符串
- 基本上就是将数据以字符串的方式拼接到HTML标签中
- 缺点 - 不同开发人员的代码风格差别很大,随着业务的复杂,后期的维护变得逐渐困难起来
- 使用前端模板引擎
- 与拼接字符串相比,代码明显规范很多,拥有一套模板语法规则
- 优点 - 大家都遵循同样的规则写代码,代码可读性明显提高了,方便后期的维护
- 缺点 - 没有专门提供事件机制
- 使用vue特有的模板语法
- 插值表达式
- 指令
- 事件绑定
- 属性绑定
- 样式绑定
- 分支循环结构
指令
-
什么是指令
- 指令的本质就是自定义属性
- 指令的格式:以v-开始(如:v-cloak)
-
v-cloak指令语法
- 插值表达式存在的问题 - 闪动
- 如何解决这个问题 - 使用v-cloak指令
- 解决该问题的原理 - 先隐藏,替换好值之后再显示最终的值
-
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>指令</title> <style> [v-cloak]{ display: none; } </style> </head> <body> <dir id="app"> <dir v-cloak>{ {msg}}</dir> </dir> <script src="../vue.js"></script> <script>z /* v-cloak指令的用法 1、提供样式 [v-cloak]{ display:none; } 2、在插值表达式所在的标签中添加v-cloak指令 */ var vm = new Vue({ el:'#app', data:{ msg:'Hello World' } }) </script> </body> </html>
数据绑定指令
-
v-text填充纯文本
-
相比于插值表达式更加简洁
-
<div v-text='msg'></div>
-
-
v-html填充HTML片段
-
存在安全问题
-
第三方的数据不可用
-
<div v-html='msg1'></div>\
-
-
v-pre填充原始信息
-
显示原始信息,跳过编译过程(分析编译过程)
-
<div v-pre>{ {msg}}</div> var vm = new Vue({ el:'#app', data:{ msg:'Hello World', msg1:'<h1>111</h1>' }
-
数据响应式
-
如何理解数据响应式
- html5中的响应式(屏幕尺寸的变化导致样式的变化)
- 数据的响应式(数据的变化导致页面内容的变化)
-
什么是数据绑定
- 将数据填充到标签中
-
v-once值编译一次
双向数据绑定
-
什么是双向数据绑定
- 用户修改页面内容,页面发生改变。页面更新内容,用户内容发生改变
-
双向数据绑定分析
- v-model指令
-
<div id="app"> <div>{ {msg}}</div> <div> <input type="text" v-model='msg'> </div> </div> <script src="../vue.js"></script> <script> var vm = new Vue({ el:'#app', data:{ msg:'111' } }) </script>
- MVVM设计思想
- M(model)
- V(view)
- VM(View-Model)
事件绑定
-
Vue如何处理事件
-
v-on指令
-
<button v-on:click='num++'>1</button>
-
v-on简写形式
-
<button @click='num++'>2</button>
-
-
事件函数的调用方式
-
直接绑定函数名称
-
<button @click='say'>3</button>
-
调用函数
-
<button @click='say()'>4</button>
-
-
事件函数参数传递
-
普通参数和事件对象
-
<div id="app"> <div>{ {num}}</div> <div> <button @click='say1'>3</button> <button @click='say2(123,456,$event)'>4</button> </div> </div> <script src="../vue.js"></script> <script> //事件绑定 var vm = new Vue({ el:'#app', data:{ num:0 }, methods:{ say2:function(a,b,event){ //这里的this是Vue的实例对象 console.log(a,b); console.log(event.target.innerHTML); this.num++ }, say1:function(event){ console.log(event.target.innerHTML); } } }) </script>
-
-
事件修饰符
-
stop阻止冒泡
-
<button v-on:click.stop='say1'>1</button>
-
-
prevent阻止默认行为
-
<a href="#" v-on:click.prevent='say2'>2</a>
-
-
-
按键修饰符
-
enter回车键
-
detele删除键
-
<div id="app"> <form action=""> <div> 用户名: <input type="text" v-on:keyup.delete='clear' v-model='name'> </div> <div> 密码: <input type="text" v-on:keyup.enter='say1' v-model='password'> </div> <div> <input type="button" v-on:click='say1' value="提交"> </div> </form> </div> <script src="../vue.js"></script> <script> var t = new Vue({ el:'#app', data:{ name:"", password:'' }, methods:{ clear:function(){ this.name = '' }, say1:function(){ console.log(this.name,this.password); } } }) </script>
-
-
-
自定义按键修饰符
-
全局config.keyCodes对象
-
<div id="app"> <input type="text" v-on:keyup.aaa='say' v-model='info'> </div> <script src="../vue.js"></script> <script> Vue.config.keyCodes.aaa = 65 var t = new Vue({ el:'#app', data:{ info:'' }, methods:{ say:function(event){ console.log(event.keyCode); } } }) </script>
-
-
简单计算器
-
通过v-model指令实现数值a和数值b的绑定
-
给计算按钮绑定事件,实现计算逻辑
-
将计算结果绑定到对应位置
-
<div id="app"> <h1>简单的计算器</h1> <div> <span>A:</span> <span> <input type="text" v-model='a'> </span> </div> <div> <span>B:</span> <span> <input type="text" v-model='b'> </span> </div> <div> <button v-on:click='say'>计算</button> </div> <div> <span>计算结果:</span> <span v-text='result'></span> </div> </div> <script src="../vue.js"></script> <script> var t = new Vue({ el:'#app', data:{ a:'', b:'', result:'' }, methods:{ say:function(){ this.result = parseInt(this.a) + parseInt(this.b) } } }) </script>
属性绑定
-
Vue如何动态处理属性
-
v-bind指令用法
-
<a v-bind:href='url'>222</a>
-
-
缩写形式
-
<a :href='url'>222</a>
-
-
-
v-model的低层实现原理分析
-
<div id="app"> <div>{ {msg}}</div> <input type="text" v-bind:value='msg' v-on:input='say'> <input type="text" v-bind:value='msg' v-on:input='msg=$event.target.value'> <input type="text" v-model='msg'> </div> <script src="../vue.js"></script> <script> var t = new Vue({ el:'#app', data:{ msg:'111' }, methods:{ say:function(event){ //使用最新的数据覆盖原有的数据 this.msg = event.target.value } } }) </script>
-
样式绑定
-
对象语法
-
<div v-bind:class="{active:isAction,error:isErro}">
-
-
数组语法
-
<div v-bind:class='[activeClass,errorClasss]'>
-
-
<div id="app"> <!-- <div v-bind:class="{active:isAction,error:isErro}"> 测试111 </div> --> <div v-bind:class='[activeClass,errorClasss]'> 111s </div> <button v-on:click='say'>切换</button> </div> <script src="../vue.js"></script> <script> var t = new Vue({ el:'#app', /* data:{ isAction:true, isErro:true }, methods:{ say:function(){ //控制isAction的值在true和false之间进行切换 this.isAction = !this.isAction this.isErro = !this.isErro } } */ data:{ activeClass:'active', errorClasss:'error' }, methods:{ say:function(){ this.activeClass = "" this.errorClasss = "" } } }) </script>
-
样式操作的细节
-
对象绑定和数组绑定可以结合使用
-
class绑定的值可以简化操作
-
默认的class会保留
-
<div id="app"> <div v-bind:class='[actionClass,errorClass,{test:isTest}]'>111</div> <div v-bind:class='arrClasses'></div> <div class="base" v-bind:class='objClasses'></div> <button v-on:click='say'>切换</button> </div> <script src="../vue.js"></script> <script> var t = new Vue({ el:'#app', data:{ actionClass:'active', errorClass:'error', isTest:'test', arrClasses:['active','error'], objClasses:{ active:true, error:true } }, methods:{ say:function(){ this.isTest = false this.objClasses.error = false } } }) </script>
-
内联样式绑定(同样式绑定)
<div id="app">
<div v-bind:style='{border:borderStyle,width:widthStyle,height:heightStyle}'></div>
<div v-bind:style='objStyles'></div>
<div v-bind:style='[objStyles,overrideStyles]'></div>
<button v-on:click='say'>切换</button>
</div>
<script src="../vue.js"></script>
<script>
var t = new Vue({
el:'#app',
data:{
borderStyle:'1px solid blue',
widthStyle:'100px',
heightStyle:'200px',
objStyles:{
border:'1px solid green',
width:'200px',
height:'100px'
},
overrideStyles:{
border:'5px solid black',
backgroundColor:'red'
}
},
methods:{
say:function(){
this.heightStyle = '100px'
this.objStyles.width = '100px'
}
}
})
</script>
分支循环结构
-
分支循环
- v-if
- v-else
- v-else-if
- v-show
-
v-if与v-show的区别
- v-if控制元素是否渲染到页面
- v-show控制元素是否显示(已经渲染到页面)
-
v-for循环
-
<div id="app"> <div>水果列表</div> <ul> <li v-for='item in arr'>{ {item}}</li> <li v-for='(item,index) in arr'>{ {item + '---' + index}}</li> <li :key='index' v-for='(item,index) in arry'> <span>{ {item.ename}}</span> <span>----</span> <span>{ {item.cname}}</span> </li> </ul> </div> <script src="../vue.js"></script> <script> var t = new Vue({ el:'#app', data:{ arr:['1','2','3','4'], arry:[{ ename:'one', cname:'1' }, { ename:'two', cname:'2' }, { ename:'three', cname:'3' }] } }) </script>
-
v-if和v-for结合使用
-
<div id="app"> <div v-if='v==12' v-for='(v,k,i) in obj'>{ {v + '---' + k + '---' + i}}</div> </div> <script src="../vue.js"></script> <script> var t = new Vue({ el:'#app', data:{ obj:{ name:'lisi', age:12, gender:'male' } } }) </script>
-
基础案例
-
实现静态UI效果
- 传统的方式实现
-
基于数据重构UI效果
-
将静态的结构和样式重构为基于Vue模板语法的形式
-
处理事件绑定和js控制逻辑
-
项目代码
-
<div id="app"> <div class="tab"> <ul> <li v-on:click='change(index)' :class='currentIndex==index?"active":""' :key='item.id' v-for='(item,index) in list'>{ {item.title}}</li> </ul> <div :class='currentIndex==index?"current":""' :key='item.id' v-for='(item, index) in list'> <img :src="item.path"> </div> </div> </div> <script type="text/javascript" src="js/vue.js"></script> <script type="text/javascript"> var vm = new Vue({ el: '#app', data: { currentIndex: 0, // 选项卡当前的索引 list: [{ id: 1, title: 'apple', path: 'img/apple.png' },{ id: 2, title: 'orange', path: 'img/orange.png' },{ id: 3, title: 'lemon', path: 'img/lemon.png' }] }, methods: { change: function(index){ // 在这里实现选项卡切换操作:本质就是操作类名 // 如何操作类名?就是通过currentIndex this.currentIndex = index; } } }); </script>
-
-
Vue常用特性
表单操作
- Input单行文本
- textarea多行文本
- select下拉多选
- radio单选框
- checkox多选框
<div id="app">
<form action="#">
<div>
<span>姓名:</span>
<!-- v-model进行数据绑定 -->
<span>
<input type="text" v-model='uname'>
</span>
</div>
<div>
<span>性别:</span>
<!-- 添加value值进行区分 -->
<span>
<input type="radio" id="male" value="1" v-model='gender'>
<label for="male">男</label>
<input type="radio" id="female" value="2" v-model='gender'>
<label for="female">女</label>
</span>
</div>
<div>
<span>爱好:</span>
<input type="checkbox" id="ball" value="1" v-model='hobby'>
<label for="ball">篮球</label>
<input type="checkbox" id="sing" value="2" v-model='hobby'>
<label for="sing">唱歌</label>
<input type="checkbox" id="code" value="3" v-model='hobby'>
<label for="code">写代码</label>
</div>
<div>
<span>职业:</span>
<select v-model='occupation' multiple = 'true'>
<option value="0">请选择职业...</option>
<option value="1">教师</option>
<option value="2">软件工程师</option>
<option value="3">律师</option>
</select>
</div>
<div>
<span>个人简介:</span>
<textarea v-model='desc'></textarea>
</div>
<div>
<input type="submit" value="提交" @click.prevent='handle'>
</div>
</form>
</div>
<script type="text/javascript" src="../vue.js"></script>
<script type="text/javascript">
var vm = new Vue({
el: '#app',
data: {
uname: 'lisi',
gender: 2,
hobby: ['2','3'],
//单选形式
// occupation: 3
//多选形式
occupation: ['2','3'],
desc: ''
},
methods: {
handle: function(){
//输出用户选择或输入的内容
// console.log(this.uname)
// console.log(this.gender)
// console.log(this.hobby.toString())
// console.log(this.occupation)
console.log(this.desc)
}
}
});
</script>
-
表单域修饰符
-
number - 转化为数值
-
trim - 去掉开始和结尾的空格
-
lazy - 将input事件切换为change事件
-
<div id="app"> <input type="text" v-model.number='age'> <input type="text" v-model.trim='info'> <input type="text" v-model.lazy='msg'> <div>{ {msg}}</div> <button @click='handle'>点击</button> </div> <script type="text/javascript" src="../vue.js"></script> <script type="text/javascript"> var vm = new Vue({ el: '#app', data:{ age: '', info: '', msg: '' }, methods:{ handle: function(){ // console.log(this.age + 13) // console.log(this.info.length) } } }); </script>
-
自定义指令
-
注意事项
- 定义是不用加v-,使用时需要加
- 钩子函数
- inserted - 被绑定元素插入父节点时调用 (仅保证父节点存在,但不一定已被插入文档中)
- 钩子函数参数
- el - 指令所绑定的元素,可以用来直接操作 DOM
- 其它详情请看官方文档
-
<div id="app"> <input type="text" v-focus> <input type="text"> </div> <script src="../vue.js"></script> <script> Vue.directive('focus', { //钩子函数 //inserted - 被绑定元素插入父节点时调用 (仅保证父节点存在,但不一定已被插入文档中) inserted: function(el){ // el表示指令所绑定的元素 //聚焦元素 el.focus(); } }); var t = new Vue({ el: '#app', data: { }, methods: { handle: function(){ } } }); </script>
-
带参数的自定义指令
-
binding
-
<div id="app"> <input type="text" v-color='msg'> </div> <script src="../vue.js"></script> <script> Vue.directive('color', { bind: function(el, binding){ // 根据指令的参数设置背景色 //console.log(binding) el.style.backgroundColor = binding.value.color; } }); var vm = new Vue({ el: '#app', data: { msg: { color: 'blue' } }, methods: { handle: function(){ } } }); </script>
-
-
-
自定义局部指令(只能在本组件中使用)
-
<div id="app"> <input type="text" v-color='msg'> <input type="text" v-focus> </div> <script src="../vue.js"></script> <script> var vm = new Vue({ el: '#app', data: { msg: { color: 'red' } }, methods: { say: function(){ } }, directives: { color: { bind: function(el, binding){ el.style.backgroundColor = binding.value.color; } }, focus: { inserted: function(el) { el.focus(); } } } }); </script>
-
计算属性
-
为了使内容更加简洁
<div id="app"> <div>{ {msg}}</div> <div>{ {reverseString}}</div> </div> <script src="../vue.js"></script> <script> var vm = new Vue({ el: '#app', data: { msg: '123' }, computed: { reverseString: function(){ //反转拼接 return this.msg.split('').reverse().join(''); } } }); </script>
-
计算属性与方法的区别
-
计算属性是基于它们的依赖(data中的数据)进行缓存的
-
方法不存在缓存
-
<div id="app"> <div>{ {reverseString}}</div> <div>{ {reverseString}}</div> <div>{ {reverseMessage()}}</div> <div>{ {reverseMessage()}}</div> </div> <script src="../vue.js"></script> <script> var vm = new Vue({ el: '#app', data: { msg: 'Nihao', num: 100 }, methods: { reverseMessage: function(){ console.log('methods') return this.msg.split('').reverse().join(''); } }, computed: { reverseString: function(){ console.log('computed') return this.msg.split('').reverse().join(''); } } }); </script>
-
过滤器
-
自定义过滤器
-
Vue.filter('upper', function(val) { return val.charAt(0).toUpperCase() + val.slice(1); });
-
-
过滤器的使用
-
局部过滤器
-
filters: { upper: function(val) { return val.charAt(0).toUpperCase() + val.slice(1); } }
-
-
整体代码
<div id="app"> <input type="text" v-model='msg'> <!-- 自定义过滤器 --> <div>{ {msg | upper}}</div> <!-- 级联操作 --> <div>{ {msg | upper | lower}}</div> <!-- 绑定数据使用过滤器 --> <div :abc='msg | upper'>测试数据</div> </div> <script src="../vue.js"></script> <script> /* 过滤器