vue2014年,由国人尤雨溪开发出来。三大框架之一
学习路线:
html/css/js=>es6=>vue基础+组件化开发=>vue核心插件vue-router+vuex=>社区技术文章=>研究底层源码
起步
引包
直接使用 <script>引入
直接下载vue.js,Vue 会被注册为一个全局变量。
<script type = 'text/javascript' src='vue.js'></script>
npm 下载
npm i vue.js -S
cdn引入
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.12"></script>
初始化
const vm = new Vue({
el:"#app",//指定绑定区域
data:{
//存放数据
msg:'str'
},
methods:{
//存放方法
getVal(){
return 'hello';
}
}
});
插值表达式
{{ }}可插任何数据,要插入变量,必须要在data中声明该属性
<body>
<div id="app">
<!-- 字符串 -->
<h2>{{'hello'}}</h2>
<!-- 数字 -->
<h2>{{520}}</h2>
<!-- 数组 -->
<h2>{{ [1,2,3] }}</h2>
<!-- 对象,注意分隔 -->
<h2>{{ {id:1} }}</h2>
<!-- 表达式,会自动计算 -->
<h2>{{ 1>2 }}</h2>
<!-- 变量 -->
<h2>{{msg}}</h2>
<!-- 函数 -->
<h2>{{getVal()}}</h2>
</div>
<script type="text/javascript">
const vm = new Vue({
el:'#app',
data:{
msg:'hello vue'
},
methods:{
getVal(){
return 520;
}
}
});
console.log(vm);
</script>
</body>
vue指令
指令 (Directives) 是带有 v- 前缀的特殊 attribute。指令 attribute 的值预期是单个 JavaScript 表达式 (v-for 是例外情况,稍后我们再讨论)。指令的作用是,当表达式的值改变时,将其产生的连带影响,响应式地作用于 DOM。
v-text
插入文本,直接渲染,与{{}}作用一样。类似于innerText
<h2 id="text" v-text="msg"></h2>
innerText表示
var text = document.getElementById('text');
text.innerText = 'hello vue';
v-html
可插入dom,类似于innerHTML
<div id="divBox" v-html="msg2"></div>
innerHTML表示
var divBox = document.getElementById('divBox');
divBox.innerHTML = '<p> hello vue1 </p>';
条件渲染
-
v-if
-
v-else-if
-
v-else
-
-
v-show
v-if
决定元素的显示与隐藏,值可以是表达式。
<div v-if="num>0">会显示</div>
<div v-else-if="num>3">显示</div>
<div v-else="">隐藏</div>
作用类似于
var num = 5;
if(num>0){
console.log('显示');
}
else if(num>3){
console.log('继续显示')
}
else{
console.log('隐藏')
}
v-show
也是决定元素是否显示,布尔值为true显示,反之。本质是修改display属性
v-if && v-show的区别(面试题)
v-if 是删除再添加元素,修改dom,v-show是改变样式,元素始终在dom结构中。两者为false时,元素在页面中均不占据位置。
建议:
- 频繁切换时,用
v-show - 切换少,用
v-if
v-bind
绑定 属性,v-bind:属性名
既可以绑定自身的属性,又可以绑定自定义的属性
<a v-bind:href = 'res.url'>{{res.name}}</a>
<script type="text/javascript">
const vm = new Vue({
el:'#app',
data:{
res:{
name:'百度',
url:'http://www.baidu.com'
}
}
});
</script>
简写方式
v-bind,简写为:
<a v-bind:href = 'res.url'>{{res.name}}</a>
<a :href = 'res.url'>{{res.name}}</a>
绑定类
可以动态切换
<h3 :class="{active:isActive}"></h3>
<script type="text/javascript">
const vm = new Vue({
el:'#app',
data:{
isActive:true,
});
</script>
绑定行内 style
<h3 :style="{color:isColor,fontSize:fontSize}"></h3>
<script type="text/javascript">
const vm = new Vue({
el:'#app',
data:{
isColor:'red',
fontSize:'16px'
});
</script>
v-on
绑定 事件,v-on:事件类型
<body>
<div id="app">
<h3>{{num}}</h3>
<button v-on:click="add">+</button>
</div>
<script type="text/javascript">
const vm = new Vue({
el: '#app',
data: {
num:0
},
methods:{
add(){
this.num++;
}
}
});
</script>
</body>
简写方式
v-on简写为 @ , @click
事件修饰符
.once只触发一次.stop阻止冒泡.prevent阻止默认事件.self.passive.capture阻止捕获
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="./JS/vue.js"></script>
</head>
<body>
<div id="app">
<button @click="warn('hello',$event)">按钮</button>
<a href="http://www.baidu.com" @click="prevent($event)">百度</a>
<a href="http://www.baidu.com" @click.prevent="sayHello">百度</a>
</div>
<script>
const vm = new Vue({
el:'#app',
methods:{
warn(text,event){
console.log(text);
console.log(event);
},
prevent(event){
if(event){
event.preventDefault()
}
},
sayHello(){
console.log('hello');
}
}
})
</script>
</body>
</html>
按键修饰符
.enter.tab.esc.space.up.down.left.right.delete
<input @keyup.enter = 'submit'>
监听事件的好处(面试题)
- 易读(容易查找)
- 无需手动销毁
- 不必在js中绑定事件
列表渲染
v-for
-
基本语法
v-for="item in arr" -
对象的操作
v-for="item in obj" -
如果是数组没有id
v-for="(item,index) in arr" :key='index' -
v-for的优先级最高
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="js/vue.js" type="text/javascript" charset="utf-8"></script>
</head>
<body>
<div id="app">
<ul>
<li v-for="item in arr" :key = 'item.id'>id:{{item.id}} 菜名:{{item.name}}</li>
<li v-for="item in obj">{{item}}</li>
</ul>
</div>
<script type="text/javascript">
const vm = new Vue({
el:'#app',
data:{
arr:[
// 数组
{
id:1,
name:'红烧肉',
},
{
id:2,
name:'锅包肉',
},
{
id:3,
name:'烧茄子'
}
],
obj:{
//对象
name:'john',
age:20,
fav(){
console.log('handsome');
}
}
}
})
</script>
</body>
</html>
绑定key(先做了解)
为了给 Vue 一个提示,以便它能跟踪每个节点的身份,从而重用和重新排序现有元素,你需要为每项提供一个唯一 key attribute
建议
在使用v-for时,给每个元素绑定key属性,有id尽量绑定id,没有绑定index。尽量是一个数值。
作用
当 Vue 正在更新使用 v-for 渲染的元素列表时,它默认使用“就地更新”的策略。如果数据项的顺序被改变,Vue 将不会移动 DOM 元素来匹配数据项的顺序,而是就地更新每个元素,并且确保它们在每个索引位置正确渲染。
v-model
你可以用 v-model 指令在表单input、textarea、select元素上创建双向数据绑定。它会根据控件类型自动选取正确的方法来更新元素。尽管有些神奇,但 v-model 本质上不过是语法糖。
v-model 会忽略所有表单元素的 value、checked、selected attribute 的初始值而总是将 Vue 实例的数据作为数据来源。你应该通过 JavaScript 在组件的 data 选项中声明初始值。
v-model 在内部为不同的输入元素使用不同的 property 并抛出不同的事件:
- text 和 textarea 元素使用
valueproperty 和input事件; - checkbox 和 radio 使用
checkedproperty 和change事件; - select 字段将
value作为 prop 并将change作为事件。
文本
对于 input文本输入,绑定的是value值 和 input事件
<body>
<div id="app">
<p>{{msg}}</p>
<input type="text" v-model="msg">
</div>
<script src="js/vue.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript">
const vm = new Vue({
el:"#app",
data:{
msg:'john'
}
});
</script>
</body>
原理
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<div id="app">
<p>{{msg}}</p>
<input type="text" :value='msg' @input='handleInput'>
</div>
<script src="js/vue.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript">
const vm = new Vue({
el:"#app",
data:{
msg:'john'
},
methods:{
handleInput(e){
this.msg = e.target.value
}
}
});
</script>
</body>
</html>
多行文本
与文本输入一致
复选框
对于复选框单选,绑定的是checked 和change事件
<body>
<div id="app">
<label for='inp'>{{checked}}</label >
<input id="inp" type="checkbox" v-model="checked">男
</div>
<script src="js/vue.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript">
const vm = new Vue({
el:"#app",
data:{
checked:false
}
});
</script>
</body>
原理
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<div id="app">
<label for='inp'>{{checked}}</label >
<input :checked='checked' type="checkbox" @change='handleChange' >男
</div>
<script src="js/vue.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript">
const vm = new Vue({
el:"#app",
data:{
checked:false
},
methods:{
handleChange(e){
this.checked = e.target.checked
}
}
});
</script>
</body>
</html>
对于复选框多选,绑定到同一个数组
<body>
<div id="app">
<p>{{checkedName}}</p>
<label for='sing'>sing</label >
<input id="sing" type="checkbox" value ='sing'v-model="checkedName" >
<label for='dance'>dance</label >
<input id="dance" type="checkbox" value ='dance'v-model="checkedName" >
<label for='sleep'>sleep</label >
<input id="sleep" type="checkbox" value ='sleep'v-model="checkedName" >
</div>
<script src="js/vue.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript">
const vm = new Vue({
el:"#app",
data:{
checkedName:[]
}
});
</script>
</body>
单选按钮
绑定checked属性和change事件
<body>
<div id="app">
<input type="radio" id="one" value="One" v-model="picked">
<label for="one">One</label>
<br>
<input type="radio" id="two" value="Two" v-model="picked">
<label for="two">Two</label>
<br>
<span>Picked: {{ picked }}</span>
</div>
<script src="js/vue.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript">
const vm = new Vue({
el:"#app",
data:{
picked:''
}
});
</script>
</body>
选择框
单选,绑定value属性和change事件
<body>
<div id="app">
<select v-model="selected">
<option disabled value="">请选择</option>
<option>A</option>
<option>B</option>
<option>C</option>
</select>
<span>Selected: {{ selected }}</span>
</div>
<script src="js/vue.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript">
const vm = new Vue({
el:"#app",
data:{
selected:''
}
});
</script>
</body>
多选 ,与复选框多选类似,绑定到一个数组
<body>
<div id="app">
<select v-model="selected" multiple style="width: 50px;">
<option>A</option>
<option>B</option>
<option>C</option>
</select>
<br>
<span>Selected: {{ selected }}</span>
</div>
<script src="js/vue.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript">
const vm = new Vue({
el:"#app",
data:{
selected:[]
}
});
</script>
</body>
修饰符
- .lazy 不同步更新
- .trim 过滤
.lazy
在默认情况下,v-model 在每次 input 事件触发后将输入框的值与数据进行同步 ,你可以添加 lazy 修饰符,从而转为在 change 事件后进行同步。
.trim
如果要自动过滤用户输入的首尾空白字符,可以给 v-model 添加 trim 修饰符。
侦听器watch
监听数据属性
<body>
<div id="app">
<input type="text" v-model="msg">
<h3>{{msg}}</h3>
</div>
<script src="js/vue.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript">
const vm = new Vue({
el:"#app",
data:{
msg:''
},
watch:{
//监听data中的属性
msg:function(newV,oldV){
console.log(`新值:${newV} 旧值:${oldV}`);
}
}
});
</script>
</body>
深度监听
当数据属性较为复杂时,就需要进行深度监听。因为普通监听,监听不到
<body>
<div id="app">
<h3>{{stus[0].name}}</h3>
<button @click="change">点击</button>
</div>
<script src="js/vue.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript">
const vm = new Vue({
el:"#app",
data:{
msg:'',
stus:[{
name:'john',
age:18
}]
},
watch:{
stus:function(newV,oldV){
console.log(`新值:${newV} 旧值:${oldV}`);//没有数据
}
},
methods:{
change(){
this.stus[0].name = 'jack'
}
}
});
</script>
</body>
深度监听
<body>
<div id="app">
<h3>{{stus[0].name}}</h3>
<button @click="change">点击</button>
</div>
<script src="js/vue.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript">
const vm = new Vue({
el:"#app",
data:{
msg:'',
stus:[{
name:'john',
age:18
}]
},
watch:{
// key是属于data对象的属性名 value:监视后的行为 newV :新值 oldV:旧值
stus:{
//深度监听
deep:true,
handler:function(newV,oldV){
console.log(newV[0].name);
}
}
},
methods:{
change(){
this.stus[0].name = 'jack'
}
}
});
</script>
</body>
计算属性computed
当模板过于复杂时,会让人难以快速识别,如:
<h3>
{{msg.split('').reverse().join('')}}
</h3>
因此就用到了计算属性。
<body>
<div id="app">
<h3>{{reverseMsg}}</h3>
</div>
<script src="js/vue.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript">
const vm = new Vue({
el:"#app",
data:{
msg:'hello',
},
computed:{
//computed默认只有getter()
reverseMsg(){
return this.msg.split('').reverse().join('');
}
}
});
</script>
</body>
优点
计算属性能够产生缓存,一旦设置了计算属性,此属性就会一直存在于内存之中,随用随取。当然,你也可以通过设置方法来达到计算属性的作用,但是需要多次调用方法。
setter()
计算属性默认只有 getter,不过在需要时你也可以提供一个 setter
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<div id="app">
<h3>{{content}}</h3>
<input type="text" v-model="content" @input="handler">
<button @click="handleClick">获取</button>
</div>
<script src="js/vue.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript">
const vm = new Vue({
el:"#app",
data:{
msg:''
},
computed:{
/* content(){
return this.msg
} */
content:{
set(newVal){
this.msg = newVal;
},
get(){
return this.msg;
}
}
},
methods:{
handler(event){
const {value} = event.target;
// this.msg = value;
this.content = value;
},
handleClick(){
if(this.content){
console.log(this.content);
}
}
}
});
</script>
</body>
</html>
过滤器filters
处理数据
局部过滤器
只能在当前实例中使用
<body>
<div id="app">
<span>{{price | myPrice('$')}}</span>
</div>
<script src="js/vue.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript">
const vm = new Vue({
el:"#app",
data:{
price:10
},
filters:{
myPrice:function(price,a){
return a+price;
}
}
});
</script>
</body>
全局过滤器
<body>
<div id="app">
<span>{{msg | myReverse}}</span>
</div>
<script src="js/vue.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript">
//全局过滤器
Vue.filter('myReverse',function(val){
return val.split('').reverse().join('');
})
const vm = new Vue({
el:"#app",
data:{
msg:'hello filter'
},
});
</script>
</body>