Vue初探

上班的第一天,我们来学学Vue吧。

这是boss说的第一句话。

那么也没有办法了。


Vue.js文档!打开!

Vue安装!做!

Vue介绍!看!

Vue示例!学!

哇这都是什么啊!

Vue!告辞!


言归正传,什么是Vue,这里截取一段文档里面的说明。

Vue.js (读音 /vjuː/,类似于 view) 是一套构建用户界面的渐进式框架。与其他重量级框架不同的是,Vue 采用自底向上增量开发的设计。Vue 的核心库只关注视图层,它不仅易于上手,还便于与第三方库或既有项目整合。另一方面,当与单文件组件Vue 生态系统支持的库结合使用时,Vue 也完全能够为复杂的单页应用程序提供驱动。

boss给我的要求是我们做一个迷你的todolist吧。

悄咪咪掏出手机查了查todo是个啥。

然后分析了一下需求。

  • 一个输入框
  • 输入框输入数据回车 -> 将事情加入计划列表
  • 输入框输入数据悬停 -> 搜索计划事项
  • 点击计划事项 -> 完成计划
  • 点击计划事项后面的关闭按钮 -> 删除此项

好的!干劲突然来了啊!

左边Vue文档CHECK!打开!

中间编辑器CHECK!ATOM!

右边浏览器CHECK!SAFARI!

好的,先撸一套最基本的。

<html>
<head>
  <meta charset="utf-8">
  <title>Todos</title>
  <style></style>
</head>
  <body>
  <script type="text/javascript"></script>
  </body>
</html>

好的,露出了满意的微笑:))

分析需求之

一个输入框


<html>
<head>
  <meta charset="utf-8">
  <title>Todos</title>
  <style></style>
</head>
  <body>
  <input type="text" placeholder="计划做些什么">
  <script type="text/javascript"></script>
  </body>
</html>

就像这个

QQ20171118-154031@2x.png

太空旷,一个挑剔的前端攻城狮是忍不了的。

加个标题,居中一下,听没听过一句话叫做字要大!

IMG_4335.JPG

然后我们加一个标题再把输入框弄好看点。

<html>
  <head>
    <meta charset="utf-8">
    <title>Todos</title>
    <style>
    //样式略,后面会展示的
    </style>
  </head>
  <body>
    <h1 id="app-title">Todos</h1><!--新的-->
    <div id="app-todos"><!--新的-->
      <div id="app-input"><!--新的-->
        <input type="text" placeholder="计划做些什么">
      </div><!--新的-->
    </div><!--新的-->
    <script type="text/javascript"></script>
  </body>
</html>

就变成了这样

QQ20171118-154906@2x.png

至少是能看了,那么接下来就是第二需求,才是vue开始的地方。

分析需求之

输入框输入数据回车 -> 将事情加入计划列表


我们先写手动写几个事件,确定一下写法还有调整一下大概的样式。

<body>
  <h1 id="app-title">Todos</h1>
  <div id="app-todos">
    <div id="app-input">
      <input type="text" placeholder="计划做些什么">
    </div>
    <ul><!--新的-->
      <li><!--新的-->
        <p>测试一下事件</p><i>X</i><!--新的-->
      </li><!--新的-->
    </ul><!--新的-->
  </div>
  <script type="text/javascript"></script>
</body>

样子也就是这样

QQ20171118-155834@2x.png

下面就是研究怎么输入回车就能够添加事件了。

我们先导入Vue,引用文档里面的话,我们选择用导入CDN上面的版本。

推荐:https://cdn.jsdelivr.net/npm/vue,会保持和 npm 发布的最新的版本一致。可以在 https://cdn.jsdelivr.net/npm/vue/ 浏览 npm 包资源。

先看修改过后的样子

QQ20171118-160711@2x.png

<body>
  <h1 id="app-title">Todos</h1>
  <div id="app-todos">
    <div id="app-input">
      <input type="text" placeholder="计划做些什么">
    </div>
    <ul>
      <li>
        <p></p><i>X</i> <!-- 注意 -->
      </li>
    </ul>
  </div>
  <!-- 引用CDN注意 -->
  <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/vue"></script>
  <script>
    //都是新的
    var todo = new Vue({
      el: "#app-todos",
      data: {
        message: "我现在是用vue里面的数据在显示"
      }
    })
  </script>
  </body>

注意到在html里面使用了 {{ message }} 作为占位符,然后此处需要展示的文字会在Vue里面定义。更改todo.message也会动态的更改html中的内容,并且还有vue自己的一套过渡效果,这样子我们就不用去担心DOM方面的问题了。只需要创建Vue的实例并把它挂载在对应的节点(element)上,通过调整实例中的值从而调整DOM。

如何创建Vue实例

var parameter = new Vue({
  el: "element" //id="element" => #element" or class="element" => ".element"
  data: {
    //some parameter
  }
})

接下来就是怎么使用input框插入message的步骤了。

首先一个计划列表肯定是很多的。所以我们需要一个数组来存放这些计划事项。所以我们先把message变成一个数组,就叫todos吧。然后在里面存放数据。

<body>
  <h1 id="app-title">Todos</h1>
  <div id="app-todos">
    <div id="app-input">
      <input type="text" placeholder="计划做些什么">
    </div>
    <ul>
      <li>
        <p></p><i>X</i>
      </li>
      <li>
        <p></p><i>X</i>
      </li>
    </ul>
  </div>
  <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/vue"></script>
  <script>
    var todo = new Vue({
      el: "#app-todos",
      data: {
        todos: [
          { text: "这里是我用数组存放的数据" },
          { text: "这里是第二个数据" }
        ]
      }
    })
  </script>
</body>

我们每添加一个新数据的时候,就要增加一对li标签。作为一个程序员,这种东西肯定是不能让自己来操作的。那么有没有一个东西可以自动生成这里li标签呢?

那么肯定是有的,那么就是Vue自带的v-for语句。

<body>
  <h1 id="app-title">Todos</h1>
  <div id="app-todos">
    <div id="app-input">
      <input type="text" placeholder="计划做些什么">
    </div>
    <ul>
      <li v-for="value in todos">
        <p></p><i>X</i>
      </li>
    </ul>
  </div>
  <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/vue"></script>
  <script>
    var todo = new Vue({
      el: "#app-todos",
      data: {
        todos: [
          { text: "这里是我用数组存放的数据" },
          { text: "这里是第二个数据" }
        ]
      }
    })
  </script>
</body>

接下来就是如何通过input输入框输入数据的问题了。vue中提供了一个v-model控件使得我们表单输入更为方便。首先它的语法是这样子的

<input v-model="message" placeholder="edit me">
<p>Message is: </p>

使用v-model控件将input的值绑定到一个Vue示例里面的数据(也可以不绑定),这样子我们可以实时获取input里面的值,能够为后面的搜索也好添加也罢做好铺垫。

为一个数组添加数据也不是什么难事,只需要执行一下todo.todos.push({text: “一些事项”}),便可以向数组里面添加数据。所以我们接下来解决的就是如何让它在用户敲下回车的时候再出发这条push语句。

这里引入vue的一个语句,通过v-on语句实现监听dom的事件。我们可以通过v-on:keyup.enter=”function”。监听回车键,一旦用户敲下回车键,那么就把input的值push到todos数组里面。先看代码。

<body>
  <h1 id="app-title">Todos</h1>
  <div id="app-todos">
    <div id="app-input">
      <input type="text" placeholder="计划做些什么" v-model="nextTodo" v-on:keyup.enter="addTodos">
    </div>
    <ul>
      <li v-for="value in todos">
        <p></p><i>X</i>
      </li>
    </ul>
  </div>
  <!-- 引用CDN注意 -->
  <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/vue"></script>
  <script>
    //都是新的
    var todo = new Vue({
      el: "#app-todos",
      data: {
        todos: [
          { text: "这里是我用数组存放的数据" },
          { text: "这里是第二个数据" }
        ],
        nextTodo: "",
      },
      methods: {
        addTodos: function(){
          this.todos.push({ text: this.nextTodo });
          this.nextTodo = "";
        }
      }
    })
  </script>
  </body>

此处我们在input里面添加了上述所说的v-model控件,然后用v-on监听了回车键。然后在vue实例里面写入了第一个方法addTodos。在按下回车的时候触发addTodos方法,addTodos方法负责把input的值push到todos数组里面并清空input的值,不在输入框里面留下残留。至此第二个需求解决。

输入框输入数据悬停 -> 搜索计划事项

初看这个需求,分析了一下归根结底这就是一个展示的区别。先前我们是用value in todos把所有的结果都展示出来。那么此处我们可以添加一个判断条件,只有计划内容是input里面的内容我们才展示出来。

<li v-for="value in todos" v-if="value.text.indexOf(nextTodo) != -1">

效果图

QQ20171119-190916@2x.png

点击计划事项 -> 完成计划

这里需要向数组里面每一个对象添加一个属性用来标记这个事件的完成情况。

然后我们通过点击的时候触发一个方法改变这个完成情况的标记。

然后css在根据完成情况做出相应改变,比如已完成的计划用删除线删除之类的。

<body>
  <h1 id="app-title">Todos</h1>
  <div id="app-todos">
    <div id="app-input">
      <input type="text" placeholder="计划做些什么" v-model="nextTodo" v-on:keyup.enter="addTodos">
    </div>
    <ul>
      <li v-for="value in todos" v-if="value.text.indexOf(nextTodo) != -1">
        <!-- 此处绑定一个click监视器 连class也可以用bind绑定-->
        <p v-on:click="completeToggle(value)" v-bind:class="{completed: value.finish, uncompleted: !value.finish}"></p><i>X</i>
      </li>
    </ul>
  </div>
  <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/vue"></script>
  <script>
    var todo = new Vue({
      el: "#app-todos",
      data: {
        //新的属性
        todos: [
          { text: "这里是我用数组存放的数据" ,finish: 0},
          { text: "这里是第二个数据"  ,finish: 0}
        ],
        nextTodo: "",
      },
      methods: {
        addTodos: function (){
          this.todos.push({ text: this.nextTodo  ,finish: 0});
          this.nextTodo = "";
        },
        //新的方法
        completeToggle: function (todo){
          todo.finish = ( todo.finish == 0 ? 1 : 0);
        }
      }
    })
  </script>
</body>

效果图

QQ20171119-192316@2x.png

此处用了v-on绑定了click事件,用v-bind绑定class的值,使得p标签的class的值跟finish的值有关,当finish为true或者1时,class=”completed”,反之class=”uncompleted”。

个人觉得v-on是用来绑定dom上面的变化,v-bind是把一些html的元素绑定到vue实例里面的属性值,从而动态改变页面效果

那么就到了最后一个需求

点击计划事项后面的关闭按钮 -> 删除此项

到这一步了熟悉vue特性的同学们也就知道,我们只需要删除todos里面的某个元素,就能够动态删除一个事件(不管是否完成,万一用户输入错误呢)

js里面删除数组元素有很多种办法,此处我选择的是splice方法,用splice删除数组元素需要提供需要删除数组的下标。但是我们用value in todos来遍历todos的时候是没有下标这个变量的,它是自增的。当我们的确需要下标这个变量来传参的时候,我们就应该这么写。

(value, key) in todos

改进后的代码

<body>
  <h1 id="app-title">Todos</h1>
  <div id="app-todos">
    <div id="app-input">
      <input type="text" placeholder="计划做些什么" v-model="nextTodo" v-on:keyup.enter="addTodos">
    </div>
    <ul>
      <li v-for="(value, key) in todos" v-if="value.text.indexOf(nextTodo) != -1">
        <p v-on:click="completeToggle(value)" v-bind:class="{completed: value.finish, uncompleted: !value.finish}"></p>
        <i v-on:click="removeTodo(key)">X</i>
      </li>
    </ul>
  </div>
  <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/vue"></script>
  <script>
    var todo = new Vue({
      el: "#app-todos",
      data: {
        todos: [
          { text: "这里是我用数组存放的数据" ,finish: 0},
          { text: "这里是第二个数据"  ,finish: 0}
        ],
        nextTodo: "",
      },
      methods: {
        addTodos: function (){
          this.todos.push({ text: this.nextTodo  ,finish: 0});
          this.nextTodo = "";
        },
        completeToggle: function (todo){
          todo.finish = ( todo.finish == 0 ? 1 : 0);
        },
        removeTodo: function (key){
          this.todos.splice(key,1);
        }
      }
    })
  </script>
</body>

至此所有功能实现完毕,觉得功能上还要改进的就是当value为空时回车不触发addTodos方法。

下面是全部的代码

<html>
  <head>
    <meta charset="utf-8">
    <title>Todos</title>
    <style>
    h1,p,ul,li,i {
      font-family: Helvetica,"PingFang SC";
    }
    html,
    body {
      height: 100%;
      width: 100%;
      padding: 0;
      margin: 0;
      margin-top: 10%;
    }
    #app-title {
      text-align: center;
      font-size: 5em;
      letter-spacing:-2px
    }
    #app-todos {
      margin-top: 0;
      margin-left:10%;
      margin-right:10%;
    }
    #app-input {
      display: flex;
      justify-content: center;
      align-items: center;
      flex-wrap: nowrap;
      height: auto;
      width: 100%;
      border: 1px solid #D4D4D4;
    }
    #app-input > input {
      height: 10%;
      width: 100%;
      font-size: 2.5em;
    }
    #app-todos > ul {
      list-style: none;
      margin-left: -40px;
      margin-top: 0;
    }
    #app-todos > ul > li {
      padding: 0;
      margin: 0;
      border: 1px solid gray;
      height: 10%;
      width: 100%;
      display: flex;
      justify-content: center;
      align-items: center;
      flex-wrap: wrap;
    }
    #app-todos > ul > li > p {
      width: 80%;
      margin: 0;
      padding: 0;
      font-size: 1.8em;
    }
    #app-todos > ul > li > i {
      float: right;
      cursor: pointer;
      transform: scale(1.3,1.3);
      font-style: normal;
    }
    .completed {
      color: #D4D4D4;
      text-decoration: line-through;
    }
    .uncompleted {
      color: black;
      text-decoration: none;
    }
    </style>
  </head>
  <body>
    <h1 id="app-title">Todos</h1>
    <div id="app-todos">
      <div id="app-input">
        <input type="text" placeholder="计划做些什么" v-model="nextTodo" v-on:keyup.enter="addTodos">
      </div>
      <ul>
        <li v-for="(value, key) in todos" v-if="value.text.indexOf(nextTodo) != -1">
          <p v-on:click="completeToggle(value)" v-bind:class="{completed: value.finish, uncompleted: !value.finish}"></p>
          <i v-on:click="removeTodo(key)">X</i>
        </li>
      </ul>
    </div>
    <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/vue"></script>
    <script>
      var todo = new Vue({
        el: "#app-todos",
        data: {
          todos: [
            { text: "这里是我用数组存放的数据" ,finish: 0},
            { text: "这里是第二个数据"  ,finish: 0}
          ],
          nextTodo: "",
        },
        methods: {
          addTodos: function (){
            this.todos.push({ text: this.nextTodo  ,finish: 0});
            this.nextTodo = "";
          },
          completeToggle: function (todo){
            todo.finish = ( todo.finish == 0 ? 1 : 0);
          },
          removeTodo: function (key){
            this.todos.splice(key,1);
          }
        }
      })
    </script>
    </body>
</html>

写这么仔细真的好麻烦啊,陆陆续续写了两天才写完,以后看看能不能这么写下去吧。毕竟我不想让这件事情变得太枯燥了。这个博客我觉得还是日常>笔记比较好一点。