Vue入门
1 Vue.js 介绍
1.1 Vue.js是什么?
Vue (读音 /vjuː/,类似于 view) 是一套用于构建用户界面的渐进式框架。与其它大型框架不同的是,Vue 被设计 为可以自底向上逐层应用. Vue 的核心库只关注视图层,不仅易于上手,还便于与第三方库或既有项目整合。另一 方面,当与现代化的工具链以及各种支持类库结合使用时,Vue 也完全能够为复杂的单页应用提供驱动。自底向上逐层应用:作为渐进式框架要实现的目标就是方便项目增量开发(即插即用)。
官方网站: https://cn.vuejs.org/v2/guide/ 作者 尤雨溪是中国人.
1.2 为甚么使用Vue?
- 声明式渲染: 前后端分离是未来趋势
- 渐进式框架: 适用于各种业务需求
- 简单易学: 国人开发,中文文档,不存在语言障碍,易于理解和学习
2 Vue.js 基础
2.1 Vue.js的使用
- 在html页面使用script引入vue.js的库即可使用。
远程CDN <script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script> 本地 <script src="vue.min.js"></script>
- Vue-CLI脚手架:使用vue.js官方提供的CLI脚本架很方便去创建vue.js工程雏形
2.2 入门程序
创建一个vuetest目录, 并且在目录下创建 01_vue入门程序.html 文件.
代码编写步骤:
1、定义html,引入vue.js
2、定义app div,此区域作为vue的接管区域
3、定义Vue实例,接管app区域。
4、定义model(数据对象)
5、在app中展示数据
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Vue入门</title>
<!-- 1.创建HTML文件, 引入vue.js 有两种方式-->
<!-- 第一种 引入 vue.js的CDN地址 -->
<!-- <script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"> </script> -->
<!-- 第二种 本地导入 -->
<script src="vue.min.js"></script>
</head>
<body>
<!-- 2. 定义app div,此区域作为vue的接管区域 -->
<div id="app">
<!-- {{}} 双括号是VUE中的差值表达式,将表达式的值输出到HTML页面 -->
{{name}}
</div>
</body>
<script>
//3. 创建vue实例
var VM = new Vue({
//定义 Vue实例挂载的元素节点,表示vue接管该div
el:'#app',
//4.定义model模型数据对象
data:{
name:"哈拉少"
}
});
</script>
</html>
-
{{}}: 插值表达式
- 插值表达式的作用?
通常用来获取Vue实例中定义的数据(data)
属性节点中 不能够使用插值表达式
- 插值表达式的作用?
-
el: 挂载点
- el的作用 ?
定义 Vue实例挂载的元素节点,表示vue接管该区域 - Vue的作用范围是什么 ?
Vue会管理el选项命中的元素,及其内部元素 - el选择挂载点时,是否可以使用其他选择器 ?
可以,但是建议使用 ID选择器 - 是否可以设置其他的DOM元素进行关联 ?
可以但是建议选择DIV, 不能使用HTML和Body标签
- el的作用 ?
-
data: 数据对象
- Vue中用到的数据定义在data中
- data中可以写复杂类型
- 渲染复杂类型数据的时候,遵守js语法
<body>
<!-- 此区域作为vue的接管区域 -->
<div id="app">
{{name}} <br>
{{school.name}} {{school.mobile}}<br>
<ul>
<li>{{names[0]}}</li>
<li>{{names[1]}}</li>
<li>{{names[2]}}</li>
</ul>
</div>
</body>
<script>
//创建vue实例
var VM = new Vue({
el:'#app',
data:{
name:"雷霆八嘎",
//对象类型数据
school:{
name:"侯哥教育",
mobile:"1001001"
},
//数组类型
names:["小斌","张百万","刘能"]
}
});
</script>
2.3 声明式渲染的好处
Vue中的声明式渲染,简单理解就是我们声明数据,Vue帮我们将数据渲染到HTML.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<div id="app">
<h2>{{name}}</h2>
</div>
</body>
<!-- jQuery中,如果 DOM 发生变化, js代码也需要做相应的改变,高耦合 .
<script src="./js/jquery-1.8.3.min.js"></script>
<script>
$(document).ready(function () {
$("#app").append("<h2>Hello Word! !</h2>");
});
</script> -->
<!-- 在用 Vue中,只需要定义好展示数据,并把它放在 DOM 合适的位置就可以. -->
<script src="js/vue.min.js"></script>
<script>
var VM = new Vue({
el: "#app",
//挂载点
data: {
name: "Hello Word! !"
}
});
</script>
</html>
2.4 Vue常用指令
根据官网的介绍,指令 是带有 v- 前缀的特殊属性。通过指令来操作DOM元素
- v-text 指令
作用: 获取data数据, 设置标签的内容.
注意: 默认写法会替换全部内容,使用插值表达式{{}}可以替换指定内容.
代码示例
<!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>v-text 指令</title>
<!-- 1 引入vue -->
<script src="js/vue.min.js"></script>
</head>
<body>
<div id="app">
<!-- v-text 获取data数据,设置标签内容,会覆盖之前的内容体-->
<h2 v-text="message">百度</h2>
<!-- 使用插值表达式,不会覆盖 -->
<h2>{{message}}百度</h2>
<!-- 拼接字符串 -->
<h2 v-text="message+1"></h2>
<h2 v-text="message+'abc'"></h2>
</div>
<script>
var VM = new Vue({
el:"#app",
data:{
message:"Java程序员"
}
})
</script>
</body>
</html>
- v-html 指令
作用: 设置元素的 innerHTML (可以向元素中写入新的标签)
代码示例
<!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>v-html 指令</title>
</head>
<body>
<div id="app">
<!-- 获取普通文本 -->
{{message}}
<h2 v-text="message"></h2>
<h2 v-html="message"></h2>
<!-- 设置元素的innerHTML -->
<h2 v-html="url"></h2>
<h2 v-text="url"></h2>
</div>
</body>
<script src="js/vue.min.js"></script>
<script>
var VM = new Vue({
el: "#app",
data: {
message: "Java程序员",
url: "<a href='https://www.baidu.com'>百度一下</a>",
},
});
</script>
</html>
- v-on 指令
作用: 为元素绑定事件, 比如: v-on:click,可以简写为 @click=“方法”
绑定的方法定义在 VUE实例的, method属性中
语法格式
<div id="app">
<!-- 使用v-on 绑定click 点击事件 -->
<input type="button" value="点击按钮" v-on:click="方法名">
<!-- 使用 @符号也可以绑定-->
<input type="button" value="点击按钮" @click="方法名">
</div>
var VM = new Vue({
el:"#app",
//通过methods ,专门存放Vue中的方法
methods:{
方法名:function(){
alert("123!")
}
}
})
代码示例
<!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>v-on 指令</title>
</head>
<body>
<div id="app">
<!-- 使用v-on 绑定click 点击事件 -->
<input type="button" value="点击按钮" v-on:click="show">
<!-- 简写 @方式 -->
<input type="button" value="点击按钮" @click="show">
<!-- 双击事件 -->
<input type="button" value="双击击按钮" @dblclick="show">
<!-- 绑定点击事件 -->
<h2 @click="changeFood">{{food}}</h2>
</div>
</body>
<script src="js/vue.min.js"></script>
<script>
var VM = new Vue({
el: "#app",
data: {
food: "麻辣小龙虾"
},
//通过methods ,专门存放Vue中的方法
methods:{
show:function(){
alert("程序员!")
},
changeFood:function(){
//使用this获取
console.log(this.food);
//在VUE中不需要考虑如何更改DOM元素, 重点放在更改数据,数据更新之后,使用数据 的那个元素会同步更新
this.food+="真好吃!";
}
}
})
</script>
</html>
-
计数器案例
-
编码步骤
- data中定义数据: 比如 num 值为1
- methods中添加两个方法: 比如add(递增) ,sub(递减)
- 使用{{}} 将num设置给 span标签
- 使用v-on 将add,sub 分别绑定给 + ,- 按钮
- 累加到10 停止
- 递减到0 停止
-
案例演示
<!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>简易计算器</title> <style> </style> </head> <body> <div id="app"> <!-- 计算功能区域 --> <div> <input type="button" @click="add" value="+"> <span>{{num}}</span> <input type="button" @click="sub" value="-"> </div> </div> </body> <script src="js/vue.min.js"></script> <script> //创建VUE实例 var VM = new Vue({ el:"#app", data:{ num:1 }, methods: { add:function(){ //console.log("add"); if(this.num < 10){ this.num++; }else{ alert("别点啦!最大了!") } }, sub:function(){ //console.log("sub"); if(this.num > 0){ this.num--; }else{ alert("别点啦!最小了!") } } } }) </script> </html >
-
案例总结
创建VUE实例时: el(挂载点) , data(数据) , methods(方法)
v-on 指令的作用是绑定事件,简写为 @
方法中使用this关键字,获取data中的数据
v-text 与 {{}} 的作用都是用来 设置元素的文本值
-
-
v-show指令
作用: v-show指令, 根据真假值,切换元素的显示状态
代码示例
<!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>v-show 指令</title>
</head>
<body>
<div id="app">
<input type="button" value="切换状态" @click="changeShow" />
<img v-show="isShow" src="./img/11.jpg" />
<img v-show="age > 18" src="./img/22.jpg" />
</div>
</body>
<script src="js/vue.min.js"></script>
<script>
var VM = new Vue({
el: "#app",
data: {
isShow: true,
age: 19,
},
methods: {
changeShow: function () {
//触发方法, 对isShow进行取反
this.isShow = !this.isShow;
},
},
});
</script>
</html>
v-show 指令总结:
原理是修改元素的display,实现显示或者隐藏
指令后面的内容,最终会解析为 布尔值
值为true 显示, 为false 则隐藏
数据改变之后,显示的状态会同步更新
- v-if 指令
作用: 根据表达值的真假,切换元素的显示和隐藏( 操纵dom 元素 )
代码示例
<!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>v-if 指令</title>
</head>
<body>
<div id="app">
<input type="button" value="切换显示状态" @click="changeShow">
<img v-if="isShow" src="./img/11.jpg" alt="">
</div>
</body>
<script src="./js/vue.min.js"></script>
<script>
var VM = new Vue({
el: "#app",
data: {
isShow: false
},
methods: {
changeShow: function () {
this.isShow = !this.isShow;
}
}
})
</script>
</html>
- v-bind 指令
作用: 设置元素的属性 (比如:src,title,class)
语法格式
v-bind:属性名=表达式
<img v-bind:src="imgSrc">
var VM = new Vue({
el:"#app",
data:{
imgSrc:"图片地址"
}
})
v-bind 可以省略,简写为冒号 :
<img :src="imgSrc">
代码示例
<!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>v-bind 指令</title>
<style>
.class01{
width: 100px;
height: 100px;
background-color: blue;
}
</style>
<script src="./js/vue.min.js"></script>
</head>
<body>
<div id="app">
<!-- 使用v-bind设置src属性值 -->
<img v-bind:src="imgSrc" alt="" width="100px">
<!-- 简写 设置title -->
<img :src="imgSrc" alt="" :title="imgTitle" width="100">
<!-- 设置class -->
<div :style="{ fontSize: size + 'px'}">v-bind指令</div>
<div v-bind:class="{class01:ccc}"></div>
<!-- 简写 -->
<div :class="c1"></div>
</div>
</body>
<script>
var VM = new Vue({
el: "#app",
data: {
imgSrc: "./img/11.jpg",
imgTitle: "我是图片标题",
size: 100 ,
ccc : true,
c1 : "class01"
}
})
</script>
</html>
v-bind指令总结
v-bind 指令的作用是: 为元素绑定属性
完整写法 v-bind:属性名,可以简写为 :属性名
- v-for 指令
作用: 根据数据生成列表结构
语法结构
<div id="app">
<ul>
<li v-for="item in arr"></li>
</ul>
</div>
var VM = new Vue({
el:"#app",
data:{
arr:[1,2,3,4,5],
objArr:[ {name:"tom"}, {name:"jack"} ]
}
})
代码示例
<!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>v-for 指令</title>
</head>
<body>
<div id="app">
<input type="button" value="添加数据" @click="add">
<input type="button" value="移除数据" @click="remove">
<ul>
<!-- 在li标签中获取数组元素 -->
<li v-for="(item,index) in arr"> {{index+1 }}城市: {{item}} </li>
</ul>
<!-- 使用h2标签显示 v-for 结合 v-bind一起使用 -->
<h2 v-for="p in persons" v-bind:title="p.name"> {{p.name}} </h2>
</div>
</body>
<script src="./js/vue.min.js"></script>
<script>
var VM = new Vue({
el:"#app",
data:{
//普通数组
arr:["上海","北京","天津","杭州"],
//对象数组
persons:[ {name:"尼古拉斯·赵四"}, {name:"莱安纳多·小沈阳"} ] },
methods: {
add:function(){
//push 添加
this.persons.push({name:"多利安·刘能"})
},
remove:function(){
this.persons.shift();
}
}
})
</script>
</html>
v-for指令总结
v-for 指令的作用: 根据数据生成列表结构
数组经常和 v-for结合使用,数组有两个常用方法:
push() 向数组末尾添加一个或多个元素
shift() 把数组中的第一个元素删除
语法是: (item,index) in 数据
item和index 可以结合其他指令一起使用
数组的长度变化,会同步更新到页面上,是响应式的
- v-on 指令补充
- 传递自定义参数 : 函数调用传参
- 事件修饰符: 对事件触发的方式进行限制
<!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>v-on 补充</title>
</head>
<body>
<div id="app">
<!-- 函数传参 -->
<input type="button" value="礼物刷起来"
@click="showTime(666,'爱你老铁!')" />
<!-- 事件修饰符 指定哪些方式可以触发事件 -->
<input type="text" @keyup.enter="hi" />
</div>
</body>
<script src="./js/vue.min.js"></script>
<script>
var VM = new Vue({
el: "#app",
data: {},
methods: {
showTime: function (p1, p2) {
console.log(p1);
console.log(p2);
},
hi: function () {
alert("你好吗?");
},
},
});
</script>
</html>
总结
事件绑定方法,可以传入自定义参数
定义方法时,需要定义形参,来接收实际的参数
事件的后面跟上 .修饰符 可以对事件进行限制
.enter 可以限制触发的按键为回车
事件修饰符有许多 使用时可以查询文档
- MVVM模式
-
MVVM 是Model-View-ViewModel 的缩写,它是一种基于前端开发的架构模式.
-
MVVM模式将页面,分层了 M 、V、和VM ,解释为:
- Model: 负责数据存储
- View: 负责页面展示
- View Model: 负责业务逻辑处理(比如Ajax请求等),对数据进行加工后交给视图展示
<body> <div id="app"> <!-- View 视图部分 --> <h2>{{name}}</h2> </div> </body> <script src="./js/vue.min.js"></script> <script> //创建的vue实例,就是 VM ViewModel var VM = new Vue({ el: "#app", //data就是MVVM模式中的 model data: { name: "hello", }, }); </script>
-
首先,我们将上图中的DOM Listeners和Data Bindings看作两个工具,它们是实现双向绑定的关键。
- 从View侧看,ViewModel中的DOM Listeners工具会帮我们监测页面上DOM元素的变化,如果有变化,则更改Model中的数据;
- 从Model侧看,当我们更新Model中的数据时,Data Bindings工具会帮我们更新页面中的DOM元素。
-
MVVM的思想,主要是为了让我们的开发更加的方便,因为MVVM提供了数据的双向绑定
- v-mode 指令
作用: 获取和设置表单元素的值(实现双向数据绑定)
- 双向数据绑定
- 单向绑定: 就是把Model绑定到View,当我们用JavaScript代码更新Model时,View就会自动更新。
- 双向绑定: 用户更新了View,Model的数据也自动被更新了,这种情况就是双向绑定。
- 什么情况下用户可以更新View呢?
- 填写表单就是一个最直接的例子。当用户填写表单时,View的状态就被更新了,如果此时MVVM框架可以自动更新Model的状态,那就相当于我们把Model和View做了双向绑定:
代码示例:
<!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>v-model</title>
</head>
<body>
<div id="app">
<input type="button" value="修改message" @click="update" />
<!-- View 视图 -->
<!-- <input type="text" v-bind:value="message" /> -->
<!-- v-model 实现双向数据绑定 -->
<input type="text" v-model="message" />
<input type="text" v-model="password" />
<h2>{{message}}</h2>
</div>
</body>
<script src="./js/vue.min.js"></script>
<script>
//VM 业务逻辑控制
var VM = new Vue({
el: "#app",
//Model 数据存储
data: {
message: "admin",
password: 123,
},
methods: {
update: function () {
this.message = "root";
},
},
});
</script>
</html>
2.5 实现简单记事本
index.css
html,
body {
margin: 0;
padding: 0;
}
body {
background: #fff ;
}
button {
margin: 0;
padding: 0;
border: 0;
background: none;
font-size: 100%;
vertical-align: baseline;
font-family: inherit;
font-weight: inherit;
color: inherit;
-webkit-appearance: none;
appearance: none;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
body {
font: 14px "Helvetica Neue", Helvetica, Arial, sans-serif;
line-height: 1.4em;
background: #f1b7b7;
color: #4d4d4d;
min-width: 230px;
max-width: 550px;
margin: 0 auto;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
font-weight: 300;
}
:focus {
outline: 0;
}
.hidden {
display: none;
}
#app {
background: #fff;
margin: 180px 0 40px 0;
position: relative;
box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.2), 0 25px 50px 0 rgba(0, 0, 0, 0.1);
}
#app input::-webkit-input-placeholder {
font-style: italic;
font-weight: 300;
color: #e6e6e6;
}
#app input::-moz-placeholder {
font-style: italic;
font-weight: 300;
color: #e6e6e6;
}
#app input::input-placeholder {
font-style: italic;
font-weight: 300;
color: gray;
}
#app h1 {
position: absolute;
top: -160px;
width: 100%;
font-size: 60px;
font-weight: 100;
text-align: center;
color: rgba(175, 47, 47, .8);
-webkit-text-rendering: optimizeLegibility;
-moz-text-rendering: optimizeLegibility;
text-rendering: optimizeLegibility;
}
.new-todo,
.edit {
position: relative;
margin: 0;
width: 100%;
font-size: 24px;
font-family: inherit;
font-weight: inherit;
line-height: 1.4em;
border: 0;
color: inherit;
padding: 6px;
border: 1px solid #999;
box-shadow: inset 0 -1px 5px 0 rgba(0, 0, 0, 0.2);
box-sizing: border-box;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.new-todo {
padding: 16px;
border: none;
background: rgba(0, 0, 0, 0.003);
box-shadow: inset 0 -2px 1px rgba(0, 0, 0, 0.03);
}
.main {
position: relative;
z-index: 2;
border-top: 1px solid #e6e6e6;
}
.toggle-all {
width: 1px;
height: 1px;
border: none; /* Mobile Safari */
opacity: 0;
position: absolute;
right: 100%;
bottom: 100%;
}
.toggle-all + label {
width: 60px;
height: 34px;
font-size: 0;
position: absolute;
top: -52px;
left: -13px;
-webkit-transform: rotate(90deg);
transform: rotate(90deg);
}
.toggle-all + label:before {
content: "❯";
font-size: 22px;
color: #e6e6e6;
padding: 10px 27px 10px 27px;
}
.toggle-all:checked + label:before {
color: #737373;
}
.listview {
margin: 0;
padding: 0;
list-style: none;
max-height: 420px;
overflow: auto;
}
.listview li {
position: relative;
font-size: 24px;
border-bottom: 1px solid #ededed;
height: 60px;
box-sizing: border-box;
}
.listview li:last-child {
border-bottom: none;
}
.listview .view .index {
position: absolute;
color: gray;
left: 10px;
top: 20px;
font-size: 16px;
}
.listview li .toggle {
text-align: center;
width: 40px;
/* auto, since non-WebKit browsers doesn't support input styling */
height: auto;
position: absolute;
top: 0;
bottom: 0;
margin: auto 0;
border: none; /* Mobile Safari */
-webkit-appearance: none;
appearance: none;
}
.listview li .toggle {
opacity: 0;
}
.listview li .toggle + label {
/*
Firefox requires `#` to be escaped - https://bugzilla.mozilla.org/show_bug.cgi?id=922433
IE and Edge requires *everything* to be escaped to render, so we do that instead of just the `#` - https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/7157459/
*/
background-image: url("data:image/svg+xml;utf8,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20width%3D%2240%22%20height%3D%2240%22%20viewBox%3D%22-10%20-18%20100%20135%22%3E%3Ccircle%20cx%3D%2250%22%20cy%3D%2250%22%20r%3D%2250%22%20fill%3D%22none%22%20stroke%3D%22%23ededed%22%20stroke-width%3D%223%22/%3E%3C/svg%3E");
background-repeat: no-repeat;
background-position: center left;
}
.listview li .toggle:checked + label {
background-image: url("data:image/svg+xml;utf8,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20width%3D%2240%22%20height%3D%2240%22%20viewBox%3D%22-10%20-18%20100%20135%22%3E%3Ccircle%20cx%3D%2250%22%20cy%3D%2250%22%20r%3D%2250%22%20fill%3D%22none%22%20stroke%3D%22%23bddad5%22%20stroke-width%3D%223%22/%3E%3Cpath%20fill%3D%22%235dc2af%22%20d%3D%22M72%2025L42%2071%2027%2056l-4%204%2020%2020%2034-52z%22/%3E%3C/svg%3E");
}
.listview li label {
word-break: break-all;
padding: 15px 15px 15px 60px;
display: block;
line-height: 1.2;
transition: color 0.4s;
}
.listview li.completed label {
color: #d9d9d9;
text-decoration: line-through;
}
.listview li .destroy {
display: none;
position: absolute;
top: 0;
right: 10px;
bottom: 0;
width: 40px;
height: 40px;
margin: auto 0;
font-size: 30px;
color: #cc9a9a;
margin-bottom: 11px;
transition: color 0.2s ease-out;
}
.listview li .destroy:hover {
color: #af5b5e;
}
.listview li .destroy:after {
content: "×";
}
.listview li:hover .destroy {
display: block;
}
.listview li .edit {
display: none;
}
.listview li.editing:last-child {
margin-bottom: -1px;
}
.footer {
color: #777;
padding: 10px 15px;
height: 20px;
text-align: center;
border-top: 1px solid #e6e6e6;
}
.footer:before {
content: "";
position: absolute;
right: 0;
bottom: 0;
left: 0;
height: 50px;
overflow: hidden;
box-shadow: 0 1px 1px rgba(0, 0, 0, 0.2), 0 8px 0 -3px #f6f6f6,
0 9px 1px -3px rgba(0, 0, 0, 0.2), 0 16px 0 -6px #f6f6f6,
0 17px 2px -6px rgba(0, 0, 0, 0.2);
}
.todo-count {
float: left;
text-align: left;
}
.todo-count strong {
font-weight: 300;
}
.filters {
margin: 0;
padding: 0;
list-style: none;
position: absolute;
right: 0;
left: 0;
}
.filters li {
display: inline;
}
.filters li a {
color: inherit;
margin: 3px;
padding: 3px 7px;
text-decoration: none;
border: 1px solid transparent;
border-radius: 3px;
}
.filters li a:hover {
border-color: rgba(175, 47, 47, 0.1);
}
.filters li a.selected {
border-color: rgba(175, 47, 47, 0.2);
}
.clear-completed,
html .clear-completed:active {
float: right;
position: relative;
line-height: 20px;
text-decoration: none;
cursor: pointer;
}
.clear-completed:hover {
text-decoration: underline;
}
.info {
margin: 50px auto 0;
color: #bfbfbf;
font-size: 15px;
text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);
text-align: center;
}
.info p {
line-height: 1;
}
.info a {
color: inherit;
text-decoration: none;
font-weight: 400;
}
.info a:hover {
text-decoration: underline;
}
/*
Hack to remove background from Mobile Safari.
Can't use it globally since it destroys checkboxes in Firefox
*/
@media screen and (-webkit-min-device-pixel-ratio: 0) {
.toggle-all,
.listview li .toggle {
background: none;
}
.listview li .toggle {
height: 40px;
}
}
@media (max-width: 430px) {
.footer {
height: 50px;
}
.filters {
bottom: 10px;
}
}
1.功能介绍
2.新增内容
步骤
- 生成列表结构(v-for 数组)
- 获取用户输入(v-model 双向绑定)
- 回车,新增数据(v-on .enter事件修饰符)
- 页面布局不熟悉,可以通过审查元素的方式快速找到元素
<!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>简单记事本</title>
<link rel="stylesheet" type="text/css" href="./css/index.css" />
</head>
<body>
<!-- VUE示例接管区域 -->
<section id="app">
<!-- 输入框 -->
<header class="header">
<h1>VUE记事本</h1> <!-- v-on 绑定事件 -->
<input v-model="inputValue" @keyup.enter="add" autofocus="autofocus"
autocomplete="off" placeholder="输入日程" class="new-todo" />
</header>
<!-- 列表区域 -->
<section class="main">
<ul class="listview">
<li class="todo" v-for="(item,index) in list">
<div class="view">
<span class="index">{{index+1}}</span>
<label>{{item}} </label>
<button class="destroy"></button>
</div>
</li>
</ul>
</section>
</section>
</body>
<script src="./js/vue.min.js"></script>
<script>
var VM = new Vue({
el:"#app",
data:{
list:["写代码","吃饭","睡觉"],
inputValue:"996还是997"
},
methods: {
//新增方法
add:function(){
//将用户输入的内容添加到list
this.list.push(this.inputValue);
}
}
})
</script>
</html>
3.删除内容
步骤
- 点击删除指定的内容( 根据索引删除元素)
- 在methods中添加一个删除的方法,使用splice函数进行删除
代码示例
<!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>简单记事本</title>
<link rel="stylesheet" type="text/css" href="./css/index.css" />
</head>
<body>
<!-- VUE示例接管区域 -->
<section id="app">
<!-- 输入框 -->
<header class="header">
<h1>VUE记事本</h1> <!-- v-on 绑定事件 -->
<input v-model="inputValue" @keyup.enter="add" autofocus="autofocus"
autocomplete="off" placeholder="输入日程" class="new-todo" />
</header>
<!-- 列表区域 -->
<section class="main">
<ul class="listview">
<li class="todo" v-for="(item,index) in list">
<div class="view">
<span class="index">{{index+1}}</span>
<label>{{item}} </label>
<!-- 删除按钮 -->
<button class="destroy" @click="remove(index)"></button>
</div>
</li>
</ul>
</section>
</section>
</body>
<script src="./js/vue.min.js"></script>
<script>
var VM = new Vue({
el:"#app",
data:{
list:["写代码","吃饭","睡觉"],
inputValue:"996还是997"
},
methods: {
//新增方法
add:function(){
//将用户输入的内容添加到list
this.list.push(this.inputValue);
},
//删除方法
remove:function(index){
console.log(index);
//使用splice(元素索引,删除几个) 根据索引删除
this.list.splice(index,1);
}
}
})
</script>
</html>
4.统计操作
步骤
- 统计页面信息的个数,就是列表中的元素的个数.
- 获取 list数组的长度,就是信息的个数
<!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>简单记事本</title>
<link rel="stylesheet" type="text/css" href="./css/index.css" />
</head>
<body>
<!-- VUE示例接管区域 -->
<section id="app">
<!-- 输入框 -->
<header class="header">
<h1>VUE记事本</h1> <!-- v-on 绑定事件 -->
<input v-model="inputValue" @keyup.enter="add" autofocus="autofocus"
autocomplete="off" placeholder="输入日程" class="new-todo" />
</header>
<!-- 列表区域 -->
<section class="main">
<ul class="listview">
<li class="todo" v-for="(item,index) in list">
<div class="view">
<span class="index">{{index+1}}</span>
<label>{{item}} </label>
<!-- 删除按钮 -->
<button class="destroy" @click="remove(index)"></button>
</div>
</li>
</ul>
</section>
<!-- 统计和清空 -->
<footer class="footer">
<span class="todo-count">
<strong>{{list.length}}</strong> items left
</span>
<button class="clear-completed"> Clear </button>
</footer>
</section>
</body>
<script src="./js/vue.min.js"></script>
<script>
var VM = new Vue({
el:"#app",
data:{
list:["写代码","吃饭","睡觉"],
inputValue:"996还是997"
},
methods: {
//新增方法
add:function(){
//将用户输入的内容添加到list
this.list.push(this.inputValue);
},
//删除方法
remove:function(index){
console.log(index);
//使用splice(元素索引,删除几个) 根据索引删除
this.list.splice(index,1);
}
}
})
</script>
</html>
总结:
- 基于数据的开发方式
- v-text设置的是文本,可以使用简化方式 {{}}
5.清空数据
步骤:
- 点击清除所有信息
- 本质就是清空数组
<!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>简单记事本</title>
<link rel="stylesheet" type="text/css" href="./css/index.css" />
</head>
<body>
<!-- VUE示例接管区域 -->
<section id="app">
<!-- 输入框 -->
<header class="header">
<h1>VUE记事本</h1> <!-- v-on 绑定事件 -->
<input v-model="inputValue" @keyup.enter="add" autofocus="autofocus"
autocomplete="off" placeholder="输入日程" class="new-todo" />
</header>
<!-- 列表区域 -->
<section class="main">
<ul class="listview">
<li class="todo" v-for="(item,index) in list">
<div class="view">
<span class="index">{{index+1}}</span>
<label>{{item}} </label>
<!-- 删除按钮 -->
<button class="destroy" @click="remove(index)"></button>
</div>
</li>
</ul>
</section>
<!-- 统计和清空 -->
<footer class="footer">
<span class="todo-count">
<strong>{{list.length}}</strong> items left
</span>
<button class="clear-completed" @click="clear()"> Clear </button>
</footer>
</section>
</body>
<script src="./js/vue.min.js"></script>
<script>
var VM = new Vue({
el:"#app",
data:{
list:["写代码","吃饭","睡觉"],
inputValue:"996还是997"
},
methods: {
//新增方法
add:function(){
//将用户输入的内容添加到list
this.list.push(this.inputValue);
},
//删除方法
remove:function(index){
console.log(index);
//使用splice(元素索引,删除几个) 根据索引删除
this.list.splice(index,1);
},
//清空数组元素
clear:function(){
this.list=[];
}
}
})
</script>
</html>