1 背景
1 vue.js是目前最火的的前端框架
APP Vue+Weex
2 react是最流行的一个前端框架
3 前端三大框架
Angular.js
vue.js
react.js
2 学前了解
1 vue
是一套构建用户界面的框架(只关注视图层)
2 mvc:后端框架
针对于后端,在后端的基础上划分了三层,model,view controller
1 model 数据连接层 mysql mongodb
2 view 视图层 前端的页面.html .jsp .ejs .php .net
3 controller 业务处理层
(1) router 分发路由
(2) service 处理具体的业务
3 mvvm:前端框架
mvvm 针对前端的 在 mvc v的基础上分为三层 model view view model
1 model 数据模型 压面用的死的数据或者是通过ajax前期后端得到的数据
2 view 视图模型 划分渲染model的区域
3 view model 管理model和view 数据的存和取
4 学习vue原因
1 提高开发效率
2 减少不必要DOM操作(改变的数据刷新)
3 双向数据绑定(只关注数据业务逻辑)
5 库和框架
- 框架
一整套完整的解决方案,对项目的侵入性较大,项目如果需要更换框架,则需要重新架构整个项目 - 库
提供某一个小功能,对项目的入侵小较小,如果某个库无法完成某些需求,可以很容易切换其他库
(1)从JQuery 切换到Zepto
(2)从EJS切换到art-template
入门使用
1 vue基本使用
代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="../js/vue.min.js"></script>
</head>
<body>
<div id="app">
{{msg}}
</div>
<script>
//1 引入vue库
//2 实例化vue
//3 渲染数据
// 模板:挂载点控制区域的标签
//model的数据必须放在模板中
// template: 显示后,将会隐藏{{msg}}信息
//
new Vue({
el:"#app",//挂载点-->控制页面的区域
data:{
msg:"hello vue!"
},
template:'<i>hello</i>'
})
</script>
</body>
</html>
解释
2 vue基本指令学习
- 渲染指令
{{}}
v-text
v-html - 属性绑定指令
v-bind: - 数据变量
- 显示隐藏
- 流程控制
1 渲染指令
代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="../js/vue.min.js"></script>
</head>
<body>
<div id="app">
<!-- 小胡子语法-->
{{msg}}
<!-- v-text -->
<h1 v-text="msg"></h1>
<h1 v-text="info"></h1>
<!-- v-html-->
<h1 v-html="msg"></h1>
<h1 v-html="info"></h1>
</div>
<script>
new Vue({
el:"#app",
data:{
msg:"我是普通文本内容",
info:"<i>我是标签文本内容</i>"
}
})
</script>
</body>
</html>
讲解
拓展
面试题: v-text和v-html区别?
1 相同点:都是用于渲染文本信息
2 不同点:v-text直接渲染字符串 v-html将字符串解析成html代码再渲染
2 v-cloak指令
代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
[v-cloak]{
display: none;
}
</style>
<script src="../js/vue.min.js"></script>
</head>
<body>
<div id="app">
<h1 v-cloak> {{msg}}</h1>
</div>
<script>
// 1 在指定标签上添加 v-cloak 指令
// 2 当vue库进入完毕后会自动的吧v-cloak删除,刚好数据也解析完毕了
new Vue({
el:"#app",
data:{
msg:"hello"
}
})
</script>
</body>
</html>
说明
拓展
面试题:如何解决页面闪烁问题?
答:
原因 小胡子语法会造成页面闪烁问题
解决:首先在指定标签上添加v-cloak指令,在vue库引入之前,添加
<style>
[v-cloak]{
display: none;
}
</style>
原理:当vue库进入完毕后会自动的吧v-cloak删除,刚好数据也解析完毕了
3 v-bind指令
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="../js/vue.min.js"></script>
</head>
<body>
<div id="app">
<!-- v-bind:属性="属性值"-->
<a href="" v-bind:title="title">我是test</a>
<!-- 简写-->
<a href="" :title="title">我是test</a>
</div>
<script>
new Vue({
el:"#app",
data:{
msg:"test",
title:"test"
}
})
</script>
</body>
</html>
4 v-bind 之 class绑定
代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="../js/vue.min.js"></script>
<style>
.bg{
background: skyblue;
}
.color{
color: pink;
}
</style>
</head>
<body>
<div id="app">
<!-- 原生-->
<h1 class="bg color"> {{msg}}</h1>
<!-- 数组-->
<h1 :class='["bg" ,"color"]'>{{msg}}</h1>
<!-- 数组三元-->
<h1 :class='["bg" ,flag?"color":""]'>{{msg}}</h1>
<!-- 数组对象 推荐-->
<h1 :class='["bg" ,{color:true}]'>{{msg}}</h1>
<!-- 对象-->
<h1 :class="{color:true,bg:false}">{{msg}}</h1>
</div>
<script>
new Vue({
el:"#app",
data:{
flag: false,
msg:"我是test"
}
})
</script>
</body>
</html>
5 v-bind之 style绑定 (使用比较少)
代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="../js/vue.min.js"></script>
</head>
<body>
<div id="app">
<h1 style="background: pink;color: green">{{msg}}</h1>
<h1 :style="{backgroundColor:'pink',color:'green'}">{{msg}}</h1>
<h1 :style="style">{{msg}}</h1>
<h1 :style="[style,style1]">{{msg}}</h1>
</div>
<script>
new Vue({
el:"#app",
data:{
msg:"hello",
style:{
backgroundColor:'pink',
color:'green'
},
style1:{
fontSize:'50px'
}
}
})
</script>
</body>
</html>
解析
6 v-on 绑定事件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="../js/vue.min.js"></script>
</head>
<body>
<div id="app">
<button v-on:click="show">点击有参</button>
<button v-on:click="show('我是有参数的')">点击有参传参</button>
<button v-on:click="show2">点我无参</button>
</div>
<script>
// 点击事件有参数但是没有传参,输出为event
new Vue({
el:"#app",
data:{
msg:"hello vue"
},
methods:{
show(str){
console.log(str)
},
show2(){
console.log("已经被点击")
}
}
})
</script>
</body>
</html>
7 阻止默认行为
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="../js/vue.min.js"></script>
<style>
.out{
height: 200px;
width: 200px;
background: pink;
}
.in{
height: 100px;
width: 100px;
background: skyblue;
}
</style>
</head>
<body>
<div id="app">
<div class="out" v-on:click="out">
<!-- <div class="in" v-on:click="inner"> 输出in out -->
<div class="in" v-on:click.stop="inner"> <!-- 输出 in 阻止冒泡 -->
</div>
</div>
<a href="https://www.baidu.com/" v-on:click.prevent="go">去百度</a><!-- 输出 go 不能跳转 阻止默认行为-->
<a href="https://www.baidu.com/" v-on:click="go">去百度</a><!-- 输出 go 能跳转 -->
</div>
<script>
new Vue({
el:"#app",
methods:{
inner (){
console.log("in")
},
out(){
console.log("out")
},
go(){
console.log("go")
}
}
})
</script>
</body>
</html>
注意
.stop 相当于 js中 evt.stopPropagation();
.prevent 想当于 js中 evt.preventDefault()
8 数据绑定
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="../js/vue.min.js"></script>
</head>
<body>
<div id="app">
<input type="text" :value="lay">
<input type="text" v-model="lay">
</div>
<script>
// vue中数据流
//1 单向数据绑定 model改变 view也跟着改变 反之不成立
//2 双向数据绑定 model改变 view也跟着改变 反之成立
new Vue({
el:"#app",
data:{
lay:"xin"
}
})
</script>
</body>
</html>
效果: 在修改第二个输入框的值是第一个也会跟着变化
拓展
面试题:数据绑定原理
1 单项数据绑定:model改变,view也跟着改变,反之不成立
2 双向数据绑定:model改变,view也跟着改变,反之成立
9 跑马灯效果
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="../js/vue.min.js"></script>
</head>
<body>
<div id="app">
<button @click="start">开始</button>
<button @click="end">暂停</button>
<h1>{{msg}}</h1>
</div>
<script>
new Vue({
el:"#app",
data:{
msg:"捕获一只小可爱!!",
timer:null
},
methods:{
start(){
//节流 判断是否已经存在定时器,如果已经存在阻止执行
if(this.timer!==null) return;
this.timer=setInterval(()=>{
let startStr=this.msg.substring(0,1);
let endStr=this.msg.substring(1);
this.msg=endStr+startStr;
},200)
},
end(){
clearInterval(this.timer);
this.timer=null;
//重新设置timer为null 方便下次使用
}
}
})
</script>
</body>
</html>
注意:
1 timer:null
2 节流
3 清空计时器置为空
10 v-for指令
代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="../js/vue.min.js"></script>
</head>
<body>
<div id="app">
<p v-for="(el,index) in arr">{{el}}-->{{index}}</p>
<p v-for="(el,key,index) in obj ">{{el}}-->{{key}}-->{{index}}</p>
<p v-for="(el,index) in arrObj">{{el}}-->{{index}}</p>
<p v-for="count in 3">{{count}}</p>
</div>
<script>
// el 元素
// index 下标
// key 值
new Vue({
el:"#app",
data:{
arr:["h","e","l","l","o"],
obj:{
id:99,
name:"lay99",
age:15
},
arrObj:[
{
id:1,
name:"lay",
age:12
},
{
id:2,
name: "sheep",
age:13
},
{
id:3,
name: "xing",
age:14
}
]
}
})
</script>
</body>
</html>
11 添加数据
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="../lib/vue.js"></script>
</head>
<body>
<div id="app">
<input type="text" v-model="name">
<button @click="addUser" >添加</button>
<!-- <input type="button" value="add" @click="addUser" >-->
<p v-for="(el,index) in arrObj" :key="el.id">{{el.id}}-->{{el.age}}-->{{el.name}}-->{{index}}</p>
</div>
<script>
// el 元素
// index 下标
// key 值
new Vue({
el:"#app",
data:{
arrObj:[
{
id:1,
name:"lay",
age:12
},
{
id:2,
name: "sheep",
age:13
},
{
id:3,
name: "xing",
age:14
}
]
},
methods:{
addUser(){
let res={
id:Date.now(),
name:this.name,
age:18
}
this.arrObj.unshift(res);
}
}
})
</script>
</body>
</html>
在本案例中遇到一个小bug
v-model获取name的值获取不到
问题:vue最新的库问题
解决办法:换一个库
13 流程指令
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="../lib/vue.js"></script>
</head>
<body>
<div id="app">
<button @click="hidden"> 显示隐藏 </button>
<button @click="flag=!flag"> 显示隐藏 </button>
<h1 v-show="flag">{{msg}}</h1>
<h1 v-if="flag">{{msg}}</h1>
<input type="text" v-model="score">
<h1 v-if="score>90">优秀</h1>
<h1 v-else-if="score>60&&score<90" >良好</h1>
<h1 v-else>不及格</h1>
</div>
<script>
// v-if 通过js控制dom元素的添加和删除 适合流程控制
//v-show 通过css控制元素的显示和隐藏 适合频繁点击操作
new Vue({
el:"#app",
data:{
msg:"hello",
flag:false,
score:88
},
methods:{
hidden(){
this.flag=!this.flag;
}
}
})
</script>
</body>
</html>
拓展
面试题
v-if和v-show的区别
1 都能控制页面上元素的消失和隐藏
2 v-if 通过js控制dom元素的添加和删除 适合流程控制
3 v-show 通过css控制元素的显示和隐藏 适合频繁点击操作
总结面试题:
1 v-text和v-html区别?
2 如何解决页面闪烁问题?
3 数据绑定原理(单项数据和双向数据)?
4 v-if和v-show的区别?
答案见上
补充
1 v-cloak v-text v-html
v-cloak 解决页面闪烁(由于网速或者其他原因造成插值表达式在页面上出现和消失)
解决:在插值表达式所在的标签上添加v-cloak并在vue库引入前添加如下的style标签内容
[v-cloak]{ display:none}
原理:在页面没加载出来隐藏插值表达式
其中v-text和v-html没有页面闪烁问题,但是会覆盖其标签内的内容
v-html会将字符串解析成html代码才会执行
2 v-bind v-on
v-bind 属性绑定 缩写为 :
v-on 事件绑定 缩写为 @
3 跑马灯案例总结
思路:
1 让第一个字符跑到最后一个字符后面(拼接字符串和获取第一个字符) 使用substring()
2 利用计时器让字符动起来
3 利用vue实例是动态监听data里面数据变化,重新渲染页面的特性,将其渲染页面
学习案例
百度换肤
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<link rel="stylesheet" href="css/reset.css">
<script src="../lib/vue.js"></script>
<style>
.bg {
width: 100%;
height: 1000px;
background: url(./images/0.jpg) no-repeat fixed 80% 80%;
background-size: cover;
position: absolute;
top: 0;
left: 0;
z-index: -1;
font-size: 12px;
font-weight: 600;
}
.toggle {
position: absolute;
top: 0;
left: 36px;
z-index: 10;
cursor: pointer;
}
.nav {
width: 100%;
height: 140px;
position: absolute;
transition: top 1s ease;
z-index: 9;
background: rgba(255, 255, 255, .8);
}
.nav .nav-list {
width: 1060px;
height: 140px;
margin: 0 auto;
}
.nav .nav-list .item {
width: 156px;
height: 100px;
background: #f7f7f7;
border-radius: 10px;
float: left;
margin: 20px 20px 0 0;
cursor: pointer;
position: relative;
}
.nav .nav-list .item img {
width: 160px;
height: 100px;
}
.nav .nav-list .item.last {
margin-right: 0;
}
.nav .nav-list .item:hover:after {
content: '';
width: 160px;
height: 100px;
text-align: center;
background: rgba(0, 0, 0, .6);
position: absolute;
top: 0;
left: 0;
z-index: 99;
}
.nav .nav-list .item .tips {
position: absolute;
top: 0;
left: 0;
z-index: 100;
width: 30px;
height: 30px;
background: url(images/tips.png) no-repeat -92px -2px;
text-align: center;
}
</style>
</head>
<body>
<div id="app">
<div class="bg" id="bg" :style="{ backgroundImage:'url(./images/'+sort2+'.jpg)'}"></div>
<div class="toggle" id="toggle" @click="flag=!flag" >
<img src="images/button.png" alt="" v-show="flag">
</div>
<div class="nav" id="nav" v-show="!flag">
<ul class="nav-list" id="nav-list">
<li class="item" v-for="(el,index) in list" @click="test(index)" :key="index" @mouseenter="bgChange(index)" @mouseleave="bgChange2(sort)">
<div class="tips" v-if="sort==index" v-show="true" ></div>
<div class="tips" v-if="sort!=index" v-show="false" ></div>
<img :src="el" alt="">
</li>
</ul>
</div>
</div>
<script src="vueStyle.js"></script>
</body>
</html>
reset.css
/**
* http://cssreset.com
*/
html, body, div, span, applet, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, abbr, acronym, address, big, cite, code,
del, dfn, em, img, ins, kbd, q, s, samp,
small, strike, strong, sub, sup, tt, var,
b, u, i, center,
dl, dt, dd, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td,
article, aside, canvas, details, embed,
figure, figcaption, footer, header,
menu, nav, output, ruby, section, summary,
time, mark, audio, video, input {
margin: 0;
padding: 0;
border: 0;
font-size: 100%;
font-weight: normal;
vertical-align: baseline;
}
/* HTML5 display-role reset for older browsers */
article, aside, details, figcaption, figure,
footer, header, menu, nav, section {
display: block;
}
body {
line-height: 1;
}
blockquote, q {
quotes: none;
}
blockquote:before, blockquote:after,
q:before, q:after {
content: none;
}
table {
border-collapse: collapse;
border-spacing: 0;
}
/* custom */
a {
color: #7e8c8d;
text-decoration: none;
-webkit-backface-visibility: hidden;
}
li {
list-style: none;
}
::-webkit-scrollbar {
width: 5px;
height: 5px;
}
::-webkit-scrollbar-track-piece {
background-color: rgba(0, 0, 0, 0.2);
-webkit-border-radius: 6px;
}
::-webkit-scrollbar-thumb:vertical {
height: 5px;
background-color: rgba(125, 125, 125, 0.7);
-webkit-border-radius: 6px;
}
::-webkit-scrollbar-thumb:horizontal {
width: 5px;
background-color: rgba(125, 125, 125, 0.7);
-webkit-border-radius: 6px;
}
html, body {
width: 100%;
}
body {
-webkit-text-size-adjust: none;
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
}
.clearfix {
zoom: 1;
}
.clear:after {
content: "1";
display: block;
clear: both;
visibility: hidden;
height: 0;
}
vueStyle.js
new Vue({
el:"#app",
data:{
list:["images/0.jpg","images/1.jpg","images/2.jpg",
"images/3.jpg","images/4.jpg","images/5.jpg"],
flag:true,
tag:true,
sort:0,
sort2:0
},
methods:{
test(index){
this.sort=index
this.tag=!this.tag;
// let arrIndex = this.spanIndex.indexOf(index);
// let res = this.tag.indexOf(index);
console.log(this.sort)
},
bgChange(index){
this.sort2=index
console.log("hhh");
console.log(index);
},
bgChange2(index){
this.sort2=this.sort;
}
}
})
源码:
链接:https://pan.baidu.com/s/1FRL4OFTud5VwQirx_LchYg
提取码:q9le