黑马VUE快速入门笔记

VUE 官网(https://v3.cn.vuejs.org/

                                                                                                点击直接进入

在这里插入图片描述

我的第一个vue程序

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>vue基础</title>

    <!-- 开发环境版本,包含了有帮助的命令行警告 -->
    <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
</head>
<body>
    <div id="app">
        {{ message }}
    </div>

    <script>
        var app = new Vue({
            el: '#app',
            data: {
                message: 'Hello Vue! 可以'
            }
        })
    </script>
</body>
</html>

el:挂载点

vue实例作用范围:vue会管理el选项命中的元素及其内部的后代元素,可以使用其他选择器(class、el标签),建议使用id选择器,因为id是唯一的。可以使用其他双标签,但是不能使用body和html。


data:数据对象

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>data:数据对象</title>

    <!-- 开发环境版本,包含了有帮助的命令行警告 -->
    <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
</head>
<body>
    <div id="app">
        {{ message }}
        <h2>{{school.name}} {{school.mobile}}</h2>
        <ul>
            <li>{{campus[0]}}</li>
            <li>{{campus[1]}}</li>
            <li>{{campus[2]}}</li>
            <li>{{campus[3]}}</li>
        </ul>
    </div>

    <script>
        var app = new Vue({
            el: '#app',
            data: {
                message: '你好,小黑',
                school:{
                    name:"黑马程序员",
                    mobile:"246566"
                },
                campus:["北京","上海","广州","深圳"]
            }
        })
    </script>
</body>
</html>
  • vue中用到的数据定义在data
  • data中可以写复杂类型的数据
  • 渲染复杂类型数据时,遵守js的语法即可

vue指令

  1. 内容绑定,事件绑定

  2. 显示切换,属性绑定

  3. 列表循环,表单元素绑定


v-text指令

  • v-text指令的作用是:设置标签的内容(textContent)
  • 默认写法会替换全部内容,使用差值表达式{{}}可以替换指定内容
  • 内部支持写表达式
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>v-text指令</title>
    <!-- 开发环境版本,包含了有帮助的命令行警告 -->
    <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
</head>
<body>
    <div id="app">
        <h2 v-text="message"></h2>
        <h2 v-text="info"></h2>
    </div>

    <script>
        var app = new Vue({
            el: '#app',
            data: {
                message: '黑马程序员',
                info:"前端移动教研部"
            }
        })
    </script>
</body>
</html>

v-html指令

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>v-html指令</title>
    <!-- 开发环境版本,包含了有帮助的命令行警告 -->
    <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
</head>
<body>
    <!--html结构-->
    <div id="app">
        <h2 v-html="content"></h2>
        <h2 v-text="content"></h2>
    </div>

    <!--创建Vue实例-->
    <script>
        var app = new Vue({
            el: '#app',
            data: {
                // content: '黑马程序员',
                content: "<a href='https://cn.vuejs.org/'>黑马程序员</a>"
            }
        })
    </script>
</body>
</html>
  • v-html指令的作用是:设置的标签innerHTML
  • 内容中有html结构会被解析为标签
  • v-text指令无论内容是什么,只会被解析为文本
  • 解析文本使用v-text,需要解析html结构使用v-html

v-on指令

<!DOCTYPE html>
<html lang="en" xmlns:v-on="http://www.w3.org/1999/xhtml">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=divice-width,initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>v-no指令基础</title>
    <!-- 开发环境版本,包含了有帮助的命令行警告 -->
    <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
</head>
<body>
    <!--html结构-->
    <div id="app">
        <input type="button" value="v-no指令" v-on:click="doIt">
        <input type="button" value="v-no简写" @click="doIt">
        <input type="button" value="双击事件" @dblclick="doIt">
        <h2 @click="changeFood">{{food}}</h2>
    </div>
    <!--创建Vue实例-->
    <script>
        var app = new Vue({
            el: '#app',
            data:{
                food:"西蓝花炒蛋!"
            },
            methods: {
                doIt:function () {
                    alert("测试");
                },
                changeFood:function () {
                    // console.log(this.food);
                    this.food+="真香!"
                }
            },
        })
    </script>
</body>
</html>
  • v-on指令的作用是:为元素绑定事件
  • 时间名不需要写on
  • 指令可以简写为@
  • 绑定的方法定义在methods属性中

计数器

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>计数器</title>
    <!-- 开发环境版本,包含了有帮助的命令行警告 -->
    <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
</head>
<body>
    <!--html结构-->
    <div id="app">
        <!--计数器功能区域-->
        <div class="input-num">
            <button @click="add">+</button>
            <span>{{num}}</span>
            <button @click="sub">-</button>
        </div>
    </div>
    <!--创建Vue实例-->
    <script>
        var app = new Vue({
            el: '#app',
            data:{
                num:1
            },
            methods: {
               add:function () {
                   if (this.num<10) {
                       this.num++;
                   }else{
                       alert("别点了,最大了");
                   }
               },
               sub:function () {
                   if (this.num>0) {
                       this.num--;
                   }else{
                       alert("别点了,最小了");
                   }
               }
            },
        })
    </script>
</body>
</html>
  • 创建vue实例是:el(挂载点),data(数据),methods(方法)
  • v-on指令的作用是绑定事件,简写@
  • 方法中通过this,关键字获取data中的数据
  • v-text指令的作用置元素的文本值,简写为{{}}
  • v-html指令的作用是:设置元素的innerHTML

v-show指令

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=divice-width,initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>v-no指令基础</title>
    <!-- 开发环境版本,包含了有帮助的命令行警告 -->
    <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
</head>
<body>
    <div id="app">
        <input type="button" value="切换显示状态" @click="changeIsShow">
        <input type="button" value="累加年龄" @click="addAge">
        <img v-show="isShow" src="草莓5.jpg">
        <img v-show="age>=18" src="草莓5.jpg">
    </div>
    <script>
        var app = new Vue({
            el: '#app',
            data:{
                isShow:false,
                age:17
            },
            methods: {
                changeIsShow:function () {
                    this.isShow = !this.isShow;
                },
                addAge:function () {
                    this.age++;
                }
            },
        })
    </script>
</body>
</html>
  • v-show指令的作用是:根据真假切换元素的显示状态
  • 原理是修改元素的display,实现显示隐藏
  • 指令后面的内容,最终会解析为布尔值
  • 值为true元素显示,值为false元素隐藏
  • 数据改变之后,对应的元素的显示状态会同步更新

v-if指令

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=divice-width,initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>v-if指令</title>
    <!-- 开发环境版本,包含了有帮助的命令行警告 -->
    <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
</head>
<body>
    <div id="app">
        <input type="button" value="切换显示" @click="toggleIsShow">
        <p v-if="isShow">黑马程序员</p>
        <p v-show="isShow">黑马程序员 - v-show修饰</p>
        <h2 v-if="temperature>50">热死了</h2>
    </div>
    <!--8888888888888888888-->
    <script>
        var app = new Vue({
            el: '#app',
            data:{
                isShow:false,
                temperature:40
            },
            methods: {
                toggleIsShow:function () {
                    this.isShow = !this.isShow;
                }
            },
        })
    </script>
</body>
</html>
  • v-if的指令的作用是:根据表达式的真假切换元素的显示状态
  • 本质是通过操纵dom元素来切换显示状态
  • 表达式的值true,元素存在dom树中,为false,从dom树中移除
  • 频繁的切换使用v-show,反之使用v-if,前者的切换消耗小

v-bind指令

<!DOCTYPE html>
<html lang="en" xmlns:v-bind="http://www.w3.org/1999/xhtml">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=divice-width,initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>v-bind指令</title>
    <!-- 开发环境版本,包含了有帮助的命令行警告 -->
    <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
    <style>
        .active{
            border: 1px solid red;
        }
    </style>
</head>
<body>
    <div id="app">
        <img v-bind:src="imgSrc" alt="">

        <img :src="imgSrc" alt="" :title="imgTitle + '!!!' "
             :class="isActive?'active':''" @click="toggleActive">

        <img :src="imgSrc" alt="" :title="imgTitle + '!!!' "
             :class="{active:isActive}" @click="toggleActive">
    </div>
    <!--******************-->
    <script>
        var app = new Vue({
            el: '#app',
            data:{
                imgSrc:"草莓5.jpg",
                imgTitle:"黑马程序员",
                isActive:false
            },
            methods: {
                toggleActive:function () {
                    this.isActive = !this.isActive;
                }
            },
        })
    </script>
</body>
</html>
  • v-bind指令的作用是:为元素绑定属性
  • 完整写法是v-bind:属性名
  • 简写的话可以直接省略v-bind,只保留:属性名
  • 需要动态的增删class建议使用对象的方式

图片切换

视频中源码链接:https://pan.baidu.com/s/1HoKF05Sx7lspVVW_HIkEdg
提取码:1234

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>图片切换</title>
    <link rel="stylesheet" href="./css/index.css" />
</head>
<body>
<div id="mask">
    <div class="center">
        <h2 class="title">
            <img src="./images/logo.png" alt="">
            深圳创维校区环境
        </h2>
        <!-- 图片 -->
        <img :src="imgArr[index]" alt="" />
        <!-- 左箭头 -->
        <!-- <a href="javascript:void(0)" v-show="index!=0" @click="prev" class="left">
          <img src="./images/prev.png" alt="" />
        </a> -->
        <a href="javascript:void(0)" v-if="index!=0" @click="prev" class="left">
            <img src="./images/prev.png" alt="" />
        </a>
        <!-- 右箭头 -->
        <a href="javascript:void(0)" v-show="index<imgArr.length-1" @click="next" class="right">
            <img src="./images/next.png" alt="" />
        </a>
    </div>
</div>

<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>

<script>
    var app = new Vue({
        el: "#mask",
        data: {
            imgArr: [
                "./images/00.jpg",
                "./images/01.jpg",
                "./images/02.jpg",
                "./images/03.jpg",
                "./images/04.jpg",
                "./images/05.jpg",
                "./images/06.jpg",
                "./images/07.jpg",
                "./images/08.jpg",
                "./images/09.jpg",
                "./images/10.jpg",
            ],
            index: 0
        },
        methods: {
            prev:function(){
                this.index--;
            },
            next:function(){
                this.index++;
            }
        },
    })
</script>
</body>
</html>

index.css--------------------图片自己弄

* {
  margin: 0;
  padding: 0;
}

html,
body,
#mask {
  width: 100%;
  height: 100%;
}

#mask {
  background-color: #c9c9c9;
  position: relative;
}

#mask .center {
  position: absolute;
  background-color: #fff;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  padding: 10px;
}
#mask .center .title {
  position: absolute;
  display: flex;
  align-items: center;
  height: 56px;
  top: -61px;
  left: 0;
  padding: 5px;
  padding-left: 10px;
  padding-bottom: 0;
  color: rgba(175, 47, 47, 0.8);
  font-size: 26px;
  font-weight: normal;
  background-color: white;
  padding-right: 50px;
  z-index: 2;
}
#mask .center .title img {
  height: 40px;
  margin-right: 10px;
}

#mask .center .title::before {
  content: "";
  position: absolute;
  width: 0;
  height: 0;
  border: 65px solid;
  border-color: transparent transparent white;
  top: -65px;
  right: -65px;
  z-index: 1;
}

#mask .center > img {
  display: block;
  width: 700px;
  height: 458px;
}

#mask .center a {
  text-decoration: none;
  width: 45px;
  height: 100px;
  position: absolute;
  top: 179px;
  vertical-align: middle;
  opacity: 0.5;
}
#mask .center a :hover {
  opacity: 0.8;
}

#mask .center .left {
  left: 15px;
  text-align: left;
  padding-right: 10px;
  border-top-right-radius: 10px;
  border-bottom-right-radius: 10px;
}

#mask .center .right {
  right: 15px;
  text-align: right;
  padding-left: 10px;
  border-top-left-radius: 10px;
  border-bottom-left-radius: 10px;
}
  • 列表数据使用数组保存
  • v-bind指令可以设置元素属性,比如src
  • v-showv-if都可以切换元素的显示状态,频繁切换用v-show

v-for指令

<!DOCTYPE html>
<html lang="en" xmlns:v-bind="http://www.w3.org/1999/xhtml">
<head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>v-for指令</title>
    <!-- 开发环境版本,包含了有帮助的命令行警告 -->
    <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
</head>
<body>
    <div id="app">
        <ul>
            <li v-for="(it,index) in arr">
                {{index+1}}、黑马程序员:{{it}}
            </li>
        </ul>
        <input type="button" value="添加数据" @click="add">
        <input type="button" value="移除数据" @click="remove">

        <h2 v-for="item in vegetables" v-bind:title="item.name">
            {{item.name}}
        </h2>
    </div>
    <script>
        var app = new Vue({
            el:"#app",
            data:{
                arr:["北京","上海","广州","深圳"],
                vegetables:[{name:"西兰花炒蛋"},{name:"蛋炒西兰花"}]
            },
            methods:{
                add:function () {
                    this.vegetables.push({name:"花菜炒蛋"});
                },
                remove:function () {
                    this.vegetables.shift();
                }
            }
        })
    </script>
</body>
</html>
  • v-for指令的作用是:根据数据生成列表结构
  • 数组经常和v-for使用
  • 语法是(item,index) in 数据
  • item和index可以结合其他指令一起使用
  • 数组长度的更新会同步到页面上,是响应式的

v-no补充

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>v-no补充</title>
    <!-- 开发环境版本,包含了有帮助的命令行警告 -->
    <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
</head>
<body>
    <div id="app">
        <input type="button" value="点击" @click="doIt(666,'老铁')">
        <input type="text" @keyup.enter="sayHi">
    </div>
    <script>
        var vue = new Vue({
            el:"#app",
            methods:{
                doIt:function (p1,p2) {
                    console.log("做IT");
                    console.log(p1);
                    console.log(p2)
                },
                sayHi:function () {
                    alert("吃了没");
                }
            }
        })
    </script>
</body>
</html>
  • 时间绑定的方法写成函数调用的形式,可以传入自定义参数
  • 定义方法时需要定义形参来接收传入的实参
  • 时间的后面跟上.修饰符可以对事件进行限制
  • .enter可以触发的按键为回车
  • 事件修饰符有多种

v-model指令

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>v-model指令</title>
    <!-- 开发环境版本,包含了有帮助的命令行警告 -->
    <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
</head>
<body>
    <div id="app">
        <input type="button" value="修改message" @click="setM">
        <input type="text" v-model="message" @keyup.enter="getM">
        <h2>{{message}}</h2>
    </div>
    <script>
        var vue = new Vue({
            el:"#app",
            data:{
                message:"黑马程序员"
            },
            methods:{
                getM:function () {
                    alert(this.message)
                },
                setM:function () {
                    this.message = "张艺兴"
                }
            }
        })
    </script>
</body>
</html>
  • v-model指令的作用是便捷的设置和获取表单元素的值
  • 绑定的数据会和表单元素相关联
  • 绑定的数据与表单元素的值是双向绑定的,无论修改哪一个都会同步更新

小黑记事本

1、新增

  1. 生成列表结构(v-for 数组
  2. 获取用户输入(v-model
  3. 回车,新增数据(v-on.enter 添加数据
  4. 总结:
    1. v-for指令的作用
    2. v-model指令的作用
    3. v-on指令,事件修饰符
    4. 通过审查元素快速定位

2、删除

思路:点击删除指定内容v-on splice 索引

  1. 数据改变和数据绑定的元素同步改变
  2. 事件的自定义参数
  3. splice方法的作用

3、统计

思路:统计信息的个数v-text length

  1. 基于数据的开发方式
  2. v-text指令的作用

4、清空

思路:点击清空索引信息v-on 清空数组

  1. 基于数据的开发方式

5、隐藏

思路:没有数据时,影藏元素v-show v-if 数组非空

6、总结

  • 列表结构可以通过v-for指令结合数据生成
  • v-on结合事件修饰符可以对事件进行限制,比如.enter
  • v-on在绑定事件时可以传递自定义参数
  • 通过v-model可以快速的设置和获取表单元素的值
  • 基于数据的开发方式
<!DOCTYPE html>
<html>
<head>
    <meta http-equiv="content-type" content="text/html; charset=UTF-8" />
    <title>小黑记事本</title>
    <meta http-equiv="content-type" content="text/html; charset=UTF-8" />
    <meta name="robots" content="noindex, nofollow" />
    <meta name="googlebot" content="noindex, nofollow" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <link rel="stylesheet" type="text/css" href="../css/index.css" />
</head>
<body>
<!-- 主体区域 -->
<section id="todoapp">
    <!-- 输入框 -->
    <header class="header">
        <h1>小黑记事本</h1>
        <input v-model="inputValue" @keyup.enter="add" autofocus="autofocus" autocomplete="off" placeholder="请输入任务"
               class="new-todo" />
    </header>
    <!-- 列表区域 -->
    <section class="main">
        <ul class="todo-list">
            <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" v-if="list.length!=0">
        <strong>{{list.length}}</strong> 条记录
      </span>
        <button class="clear-completed" @click="clear" v-show="list.length!=0">
            清空
        </button>
    </footer>
</section>
<!-- 底部 -->
<footer class="info">
    <p>
        <a href="http://www.itheima.com/"><img src="../img/black.png" alt="" /></a>
    </p>
</footer>
<!-- 开发环境版本,包含了有帮助的命令行警告 -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
    var app = new Vue({
        el: "#todoapp",
        data: {
            list: ["写代码", "吃饭饭", "睡觉觉"],
            inputValue: "小伙子又开始卷了"
        },
        methods: {
            add: function () {
                this.list.push(this.inputValue);
            },
            remove:function(index){
                console.log("删除");
                console.log(index+1);
                this.list.splice(index,1);
            },
            clear:function () {
                this.list = [];
            }
        },
    })
</script>
</body>
</html>

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: #f5f5f5;
  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;
}

#todoapp {
  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);
}

#todoapp input::-webkit-input-placeholder {
  font-style: italic;
  font-weight: 300;
  color: #e6e6e6;
}

#todoapp input::-moz-placeholder {
  font-style: italic;
  font-weight: 300;
  color: #e6e6e6;
}

#todoapp input::input-placeholder {
  font-style: italic;
  font-weight: 300;
  color: gray;
}

#todoapp 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;
}

.todo-list {
  margin: 0;
  padding: 0;
  list-style: none;
  max-height: 420px;
  overflow: auto;
}

.todo-list li {
  position: relative;
  font-size: 24px;
  border-bottom: 1px solid #ededed;
  height: 60px;
  box-sizing: border-box;
}

.todo-list li:last-child {
  border-bottom: none;
}

.todo-list .view .index {
  position: absolute;
  color: gray;
  left: 10px;
  top: 20px;
  font-size: 16px;
}

.todo-list 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;
}

.todo-list li .toggle {
  opacity: 0;
}

.todo-list 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;
}

.todo-list 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");
}

.todo-list li label {
  word-break: break-all;
  padding: 15px 15px 15px 60px;
  display: block;
  line-height: 1.2;
  transition: color 0.4s;
}

.todo-list li.completed label {
  color: #d9d9d9;
  text-decoration: line-through;
}

.todo-list 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;
}

.todo-list li .destroy:hover {
  color: #af5b5e;
}

.todo-list li .destroy:after {
  content: "×";
}

.todo-list li:hover .destroy {
  display: block;
}

.todo-list li .edit {
  display: none;
}

.todo-list 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,
  .todo-list li .toggle {
    background: none;
  }

  .todo-list li .toggle {
    height: 40px;
  }
}

@media (max-width: 430px) {
  .footer {
    height: 50px;
  }

  .filters {
    bottom: 10px;
  }
}

网络应用

1、介绍

  • Vue结合网络数据库开发应用
  • axios(网络请求库
  • axios+vue(结合vue一起
  • 天气预报案例

2、axios基本使用

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>axios 基本使用</title>
</head>
<body>
    <input type="button" value="get请求" class="get">
    <input type="button" value="post请求" class="post">
    <!--官网提供的 axios 在线地址-->
    <script src="https://unpkg.com/axios/dist/axios.min.js"></script>
    <script>
        /*
            接口1:随机笑话
            请求地址:https://autumnfish.cn/api/joke/list
            请求方法:get
            请求参数:num(笑话条数,数字)
            响应内容:随机笑话
        */
        document.querySelector(".get").onclick = function () {
            axios.get("https://autumnfish.cn/api/joke123/list?num=3")
                .then(function (response) {
                    console.log(response);
                },function (err) {
                    console.log(err);
            })
        }
        /*
            接口2:用户注册
            请求地址:https://autumnfish.cn/api/user/reg
            请求方法:post
            请求参数:username(用户名,字符串)
            响应内容:注册成功或失败
        */
        document.querySelector(".post").onclick = function () { 
            axios.post("https://autumnfish.cn/api/user/reg1",
                {username:"张艺兴"})
                .then(function (response) {
                    console.log(response);
                },function (err) {
                    console.log(err);
                })
        }
    </script>
</body>
</html>

axios官网传送门: http://www.axios-js.com/zh-cn/docs/

  • axios必须先导入才可以使用
  • 使用getpost方法即可发送对应的请求
  • then方法中的回调函数会在请求成功或失败时触发
  • 通过回调函数的形参可以获取响应内容,或错误信息

3、axios加vue

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>axios与vue结合使用</title>
</head>
<body>
<div id="app">
    <input type="button" value="获取笑话" @click="getJoke">
    <p>{{joke}}</p>
</div>
<!-- 开发环境版本,包含了有帮助的命令行警告 -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<!-- 官网提供的 axios 在线地址 -->
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script>
    /*
        接口:随机获取一条笑话
        请求地址:https://autumnfish.cn/api/joke
        请求方法:get
        请求参数:无
        响应内容:随机笑话
    */
    var app=new Vue({
        el:"#app",
        data:{
            joke:"获取笑话",
        },
        methods:{
            getJoke:function () {
                // console.log(this.joke);
                var that = this;
                axios.get("https://autumnfish.cn/api/joke").then(
                    function (response) {
                        // console.log(response);
                        console.log(response.data);
                        // console.log(this.joke);
                        that.joke = response.data;
                    },function (err) { })
            }
        }
    })
</script>
</body>
</html>
  • axios回调函数中的this已经改变,无法访问到data中数据
  • this保存起来,回调函数中直接使用保存的this即可
  • 和本地应用的最大区别就是改变了数据来源

4、天知道

回车查询
  1. 按下回车(v-on .enter)
  2. 查询数据(axios 接口 v-model)
  3. 渲染数据(v-for 数组 that)
  • 应用的逻辑代码建议和页面分离,使用单独的js文件编写
  • axios回调函数中this指向改变了,需要额外保存一份
  • 服务器返回的数据比较复杂时,获取的时候需要注意层级结构
点击查询
  1. 点击城市(v-on 自定义参数
  2. 查询数据(this.方法()
  3. 渲染数据
  • 自定义参数可以让代码的复用性更高
  • methods中定义的方法内部,可以通过this关键字点出其他方法

视频中源码链接:https://pan.baidu.com/s/1HoKF05Sx7lspVVW_HIkEdg
提取码:1234

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>天知道</title>
    <link rel="stylesheet" href="css/reset.css" />
    <link rel="stylesheet" href="css/index.css" />
</head>
<body>
<div class="wrap" id="app">
    <div class="search_form">
        <div class="logo"><img src="img/logo.png" alt="logo" /></div>
        <div class="form_group">
            <input type="text" v-model="city"  @keyup.enter="searchWeather"   class="input_txt" placeholder="请输入查询的天气"/>
            <button class="input_sub">
                搜 索
            </button>
        </div>
        <div class="hotkey">
            <a href="javascript:;" @click="changeCity('北京')">北京</a>
            <a href="javascript:;" @click="changeCity('上海')">上海</a>
            <a href="javascript:;" @click="changeCity('广州')">广州</a>
            <a href="javascript:;" @click="changeCity('深圳')">深圳</a>
        </div>
    </div>
    <ul class="weather_list">
        <li v-for="item in weatherList">
            <div class="info_type"><span class="iconfont">{{ item.type }}</span></div>
            <div class="info_temp">
                <b>{{ item.low }}</b>
                ~
                <b>{{ item.high }}</b>
            </div>
            <div class="info_date"><span>{{ item.date }}</span></div>
        </li>
    </ul>
</div>
<!-- 开发环境版本,包含了有帮助的命令行警告 -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<!-- 官网提供的 axios 在线地址 -->
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<!-- 自己的js -->
<script src="js/main.js"></script>
</body>
</html>

main.js

/*
  请求地址:http://wthrcdn.etouch.cn/weather_mini
  请求方法:get
  请求参数:city(城市名)
  响应内容:天气信息
  */
var app = new Vue({
    el:"#app",
    data:{
        city:'',
        weatherList:[]
    },
    methods:{
        searchWeather:function () {
            // console.log('天气查询');
            // console.log(this.city);
            //调用接口
            //保存this
            var that = this;
            axios.get('http://wthrcdn.etouch.cn/weather_mini?city='+this.city)
                .then(function (response) {
                    // console.log(response);
                    // console.log(response.data.data.forecast);
                    that.weatherList = response.data.data.forecast
                })
                .catch(function (err) {  })
        },
        changeCity:function (city) {
            this.city = city;
            this.searchWeather();
        }
    }
})

综合应用

1、介绍

  1. 歌曲搜索
  2. 歌曲播放
  3. 歌曲封面
  4. 歌曲评论
  5. 播放动画
  6. mv播放

2、音乐查询

  1. 按下回车(v-on .enter)
  2. 查询数据(axios 接口 v-model)
  3. 渲染数据(v-for 数组 that)
  • 服务器返回的数据比较复杂时,获取的时候需要注意层级结构
  • 通过审查元素快速定位到需要操纵的元素

3、音乐播放

  1. 点击播放(v-on 自定义参数
  2. 歌曲地址获取(接口 歌曲id
  3. 歌曲地址设置(v-bind
  • 歌曲id依赖歌曲搜索的结果,对于不用的数据也需要关注

4、歌曲封面

  1. 点击播放(增加逻辑
  2. 歌曲封面获取(接口 歌曲id
  3. 歌曲封面设置(v-bind
  • 在vue中通过v-bind操纵属性
  • 本地无法获取的数据,基本都会有对应的接口

5、歌曲评论

  1. 点击播放(增加逻辑
  2. 歌曲评论获取(接口 歌曲id
  3. 歌曲评论渲染(v-for
  • 这vue中通过v-for生成列表

6、播放动画

  1. 监听音乐播放(v-on play
  2. 监听音乐暂停(v-on pause
  3. 操纵类名(v-bind 对象
  • audio标签的play事件会在音频播放的时候触发
  • audio标签的pause事件会在音频暂停的时候触发
  • 通过对象的方式设置类名,类名生效与否取决于后面值的真假

7、播放MV

  1. mv图标显示(v-if
  2. mv地址获取(接口 mvid
  3. 遮罩层(v-show v-on
  4. mv地址设置(v-bind
  • 不同的接口需要的数据是不同的,文档的阅读需要仔细
  • 页面结构复杂之后,通过审查元素的方式去,快速定位相关元素
  • 响应式的数据都需要定义在data

悦听代码

视频中源码链接:https://pan.baidu.com/s/1HoKF05Sx7lspVVW_HIkEdg
提取码:1234

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8" />
    <meta name="viewport" conte -nt="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>悦听</title>
    <!-- 样式 -->
    <link rel="stylesheet" href="./css/index.css">
</head>

<body>
<div class="wrap">
    <!-- 播放器主体区域 -->
    <div class="play_wrap" id="player">
        <div class="search_bar">
            <img src="images/player_title.png" alt="" />
            <!-- 搜索歌曲 -->
            <input type="text" autocomplete="off" v-model="query" @keyup.enter="searchMusic" />
        </div>
        <div class="center_con">
            <!-- 搜索歌曲列表 -->
            <div class='song_wrapper'>
                <ul class="song_list">
                    <li v-for="item in musicList">
                        <a href="javascript:;" @click="playMusic(item.id)"></a>
                        <b>{{ item.name }}</b>
                        <span v-if="item.mvid!=0" @click="playMV(item.mvid)"><i></i></span>
                    </li>
                </ul>
                <img src="images/line.png" class="switch_btn" alt="">
            </div>
            <!-- 歌曲信息容器 -->
            <div class="player_con" :class="{playing:isPlaying}">
                <img src="images/player_bar.png" class="play_bar" />
                <!-- 黑胶碟片 -->
                <img src="images/disc.png" class="disc autoRotate" />
                <img :src="musicCover" class="cover autoRotate" />
            </div>
            <!-- 评论容器 -->
            <div class="comment_wrapper">
                <h5 class='title'>热门留言</h5>
                <div class='comment_list'>
                    <dl v-for="item in hotComments">
                        <dt><img :src="item.user.avatarUrl" alt=""></dt>
                        <dd class="name">{{ item.nickname}}</dd>
                        <dd class="detail">
                            {{ item.content }}
                        </dd>
                    </dl>
                </div>
                <img src="images/line.png" class="right_line">
            </div>
        </div>
        <div class="audio_con">
            <audio ref='audio' @play="play" @pause="pause" :src="musicUrl" controls autoplay loop class="myaudio"></audio>
        </div>
        <div class="video_con" v-show="isShow" style="display: none;">
            <video :src="mvUrl" controls="controls"></video>
            <div class="mask" @click="hide"></div>
        </div>
    </div>
</div>
<!-- 开发环境版本,包含了有帮助的命令行警告 -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<!-- 官网提供的 axios 在线地址 -->
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script src="./js/main.js"></script>
</body>
</html>

main.js

/*
  1:歌曲搜索接口
    请求地址:https://autumnfish.cn/search
    请求方法:get
    请求参数:keywords(查询关键字)
    响应内容:歌曲搜索结果

  2:歌曲url获取接口
    请求地址:https://autumnfish.cn/song/url
    请求方法:get
    请求参数:id(歌曲id)
    响应内容:歌曲url地址
  3.歌曲详情获取
    请求地址:https://autumnfish.cn/song/detail
    请求方法:get
    请求参数:ids(歌曲id)
    响应内容:歌曲详情(包括封面信息)
  4.热门评论获取
    请求地址:https://autumnfish.cn/comment/hot?type=0
    请求方法:get
    请求参数:id(歌曲id,地址中的type固定为0)
    响应内容:歌曲的热门评论
  5.mv地址获取
    请求地址:https://autumnfish.cn/mv/url
    请求方法:get
    请求参数:id(mvid,为0表示没有mv)
    响应内容:mv的地址
*/
var app = new Vue({
    el: "#player",
    data: {
        // 查询关键字
        query: "",
        // 歌曲数组
        musicList: [],
        // 歌曲地址
        musicUrl: "",
        // 歌曲封面
        musicCover: "",
        // 歌曲评论
        hotComments: [],
        // 动画播放状态
        isPlaying: false,
        // 遮罩层的显示状态
        isShow: false,
        // mv地址
        mvUrl: ""
    },
    methods: {
        // 歌曲搜索
        searchMusic: function() {
            var that = this;
            axios.get("https://autumnfish.cn/search?keywords=" + this.query).then(
                function(response) {
                    // console.log(response);
                    that.musicList = response.data.result.songs;
                    console.log(response.data.result.songs);
                },
                function(err) {}
            );
        },
        // 歌曲播放
        playMusic: function(musicId) {
            //   console.log(musicId);
            var that = this;
            // 获取歌曲地址
            axios.get("https://autumnfish.cn/song/url?id=" + musicId).then(
                function(response) {
                    // console.log(response);
                    // console.log(response.data.data[0].url);
                    that.musicUrl = response.data.data[0].url;
                },
                function(err) {}
            );

            // 歌曲详情获取
            axios.get("https://autumnfish.cn/song/detail?id=" + musicId).then(
                function(response) {
                    // console.log(response);
                    // console.log(response.data.songs[0].al.picUrl);
                    that.musicCover = response.data.songs[0].al.picUrl;
                },
                function(err) {}
            );

            // 歌曲评论获取
            axios.get("https://autumnfish.cn/comment/hot?type=0&id=" + musicId).then(
                function(response) {
                    // console.log(response);
                    // console.log(response.data.hotComments);
                    that.hotComments = response.data.hotComments;
                },
                function(err) {}
            );
        },
        // 歌曲播放
        play: function() {
            // console.log("play");
            this.isPlaying = true;
        },
        // 歌曲暂停
        pause: function() {
            // console.log("pause");
            this.isPlaying = false;
        },
        // 播放mv
        playMV: function(mvid) {
            var that = this;
            axios.get("https://autumnfish.cn/mv/url?id=" + mvid).then(
                function(response) {
                    // console.log(response);
                    console.log(response.data.data.url);
                    that.isShow = true;
                    that.mvUrl = response.data.data.url;
                },
                function(err) {}
            );
        },
        // 隐藏
        hide: function() {
            this.isShow = false;
        }
    }
});
  • 11
    点赞
  • 50
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

HY丶浪潮

感谢支持,让自己变更好

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值