美文网首页
【前端】Vue.js 基础篇(上)

【前端】Vue.js 基础篇(上)

作者: irenb | 来源:发表于2020-01-31 17:04 被阅读0次

前言

前端开发发展历程,目的都是为了提高开发效率:

  1. 原生JS
  2. Jquery之类的类库(解决不同浏览器兼容性问题)
  3. 前端模板引擎(避免频繁操作DOM元素,调用前端模板引擎提供的方法自动渲染页面)
  4. Vue.js / Angular.js 等(直接用框架提供的指令把数据渲染到页面上,不需要进行DOM操作,提高渲染效率)

三大主流框架:主流的 MVVM 框架有 Angular, React 和 Vue.js。

双向数据绑定:通过框架提供的指令直接绑定数据,只关注数据的业务逻辑,不再操作DOM元素。

什么是 Vue.js

  • Vue.js(读音 /vju/, 类似于 view),是一套构建用户界面的前端框架(视图层)。
  • 借助 Weex 也可以使用 Vue 语法进行手机APP开发。

Vue框架的好处:数据绑定,指令,轻量级,插件化。
官网:https://cn.vuejs.org

框架和库的区别

  • 框架:是一套完整的解决方案,对项目的侵入性较大,更换麻烦。
  • 库(插件):只是某一个小功能,对项目的侵入性较小,容易更换。

MVVM设计模式

MVVM是Model-View-ViewModel的简写。它本质上是MVC的改进版。MVVM就是将其中的View的状态和行为抽象化,让我们将视图UI和业务逻辑分开。

MVVM模式和MVC模式一样,主要目的是分离视图(View)和模型(Model)。

Vue.js是一个提供了MVVM风格的双向数据绑定的JavaScript库,专注于View层。它的核心是MVVM中的VM(ViewModel)。ViewModel负责连接View和Model,保证视图和数据的一致性,这种轻量级的架构让前端开发更加高效、便捷。

传统写法:红框中的是逻辑部分,灰框中的是赋值部分(逻辑和赋值在一起)。



Vue解决的问题是:逻辑部分和视图部分进行分离。

Vue 的基本使用

<!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>Document</title>
  <!-- 1. 导入Vue的包 -->
  <script src="./lib/vue-2.4.0.js"></script>
</head>

<body>
  <!-- 将来 new 的Vue实例,会控制这个 元素中的所有内容 -->
  <div id="app">
    <p>{{ msg }}</p>
  </div>

  <script>
    // 2. 创建一个Vue的实例
    // 当我们导入包之后,在浏览器的内存中,就多了一个 Vue 构造函数
    // 注意:我们 new 出来的这个 app 对象,就是我们 MVVM中的 VM调度者
    var app = new Vue({
      // 指定控制区域(由 Vue 接管 id 为 app 的区域)
      el: '#app',  // 表示,当前我们 new 的这个 Vue 实例,要控制页面上的哪个区域
      // 这里的 data 就是 MVVM中的 M,专门用来保存 每个页面的数据的
      data: { // data 属性中,存放的是 el 中要用到的数据
        msg: '欢迎学习Vue' // 通过 Vue 提供的指令,很方便的就能把数据渲染到页面上,程序员不再手动操作DOM元素了【前端的Vue之类的框架,不提倡我们去手动操作DOM元素了】
      }
    })
  </script>
</body>

</html>

Vue 指令

  • {{ }}:插值表达式

  • 绑定数据(渲染值)指令:

<!-- 1.插值表达式:使用 v-cloak 能够解决 "{{ msg }}" 显示闪烁的问题 -->
<p v-cloak>{{ msg }}</p>
<!-- 2.使用 v-text 指令:默认没有闪烁问题,会覆盖元素中原本的内容 -->
<p v-text="msg">内容</p>
<!-- 3.使用 v-html 指令:可以输出带 HTML 标签的文本(赋值内容为富文本) -->
<p v-html="msg">内容</p>
  • 绑定属性指令 v-bind:属性名
<!-- 这里的 mytitle 是普通文本 -->
<input type="button" value="按钮" title="mytitle">

<!-- v-bind:绑定 title 属性,告诉这里的 mytitle 是变量,即会当JS代码去执行 -->
<!-- v-bind 指令的意思是:将这个元素节点的 title attribute 和 Vue 实例的 mytitle property 保持一致 -->
<input type="button" value="按钮" v-bind:title="mytitle">
<!-- "v-bind:" 可以缩写成 ":" -->
<input type="button" value="按钮" :title="mytitle">

<!-- v-bind 只能实现数据的单向绑定,从 M 自动绑定到 V, 无法实现数据的双向绑定  -->
  • 绑定事件指令 v-on:事件名
<!-- 绑定点击事件 -->
<input type="button" value="按钮" v-on:click="show">
<!-- 绑定鼠标移动覆盖事件 -->
<input type="button" value="按钮" v-on:mouseover="show">

<!-- "v-on:" 可以缩写成 "@" -->
<input type="button" value="按钮" @click="show">

<!-- 方法后面可以传参数, prevent 是阻止默认行为(即不执行href的跳转) -->
<a href="" @click.prevent="delete(item.id)">删除</a>

<script>
    var app = new Vue({
      el: '#app',
      data: {
        msg: '123',
        mytitle: '这是一个自己定义的title'
      },
      methods: { // 这个 methods属性中定义了当前Vue实例所有可用的方法
        show: function () {
          alert('Hello')
        }
      }
    })

   /* 
      document.getElementById('btn').onclick = function(){
        alert('Hello')
      }
   */
</script>

// 注意1:在 app 实例中,如果想要获取 data 上的数据,或者 想要调用 methods 中的 方法,必须通过 this.数据属性名  或  this.方法名 来进行访问,这里的this,就表示 我们 new 出来的 app  实例对象
// 注意2:app 实例,会监听自己身上 data 中所有数据的改变,只要数据一发生变化,就会自动把 最新的数据,从data 上同步到页面中去;【好处:程序员只需要关心数据,不需要考虑如何重新渲染DOM页面】
  • 列表渲染 v-for
<!-- 遍历数组:list 是数据源数据,item 是数组的每一项 -->
<p v-for="item in list">{{ item }}</p>
<!-- 遍历数组:list 是数据源数据,item 是数组的每一项,i 是索引 -->
<p v-for="(item, i) in list">索引值:{{ i }} , 每一项:{{ item }}</p>
<!-- 数组的每一项也可以用其它名称 -->
<p v-for="obj in list">{{ obj.name }}</p>

<!-- 遍历对象 -->
<p v-for="(val, key) in obj">值:{{ val }} ;键:{{ key }}</p>
<p v-for="(val, key, i) in obj">值:{{ val }} ;键:{{ key }};索引:{{ i }}</p>

<!-- in 后面可以是数组,对象,或数字 -->
<!-- 注意:如果使用 v-for 迭代数字的话,前面的 count 值从 1 开始 -->
<p v-for="count in 10">这是第 {{ count }} 次循环</p>

<!-- 在2.2.0+版本里,key是必须设置的(数字/字符串类型),便于跟踪每个节点的唯一性 -->
<p v-for="item in list" :key="item.id">{{ item.name }}</p>
  • 条件渲染
<!-- v-if 的特点:每次都会重新删除或创建元素 -->
<!-- v-show 的特点:每次不会重新进行DOM的删除和创建操作,只是切换了元素的 display:none 样式 -->
<h1 v-if="flag">这是用v-if控制的元素</h1>
<h1 v-show="flag">这是用v-show控制的元素</h1>

定时器的使用

// 开启一个定时器
var interval = setInterval(() => {
    // 执行定时任务
}, 500);

// 停止定时器
clearInterval(interval);
interval = null;

事件修饰符

  • .stop 阻止事件冒泡
<!-- 默认是事件冒泡(从里往外执行):即点击按钮先执行 btnClick,后执行 divClick -->
<div class="inner" @click="divClick">
     <input type="button" value="按钮" @click.stop="btnClick">
</div>
  • .prevent 阻止默认行为
<!-- 阻止默认行为,即不执行href的跳转 -->
<a href="http://www.baidu.com" @click.prevent="linkClick">有问题,先去百度</a>
  • .capture 实现捕获触发事件的机制
<!-- 从外往里执行:即点击按钮先执行 divClick,后执行btnClick -->
<div class="inner" @click.capture="divClick">
     <input type="button" value="按钮" @click="btnClick">
</div>
  • .self 实现只有点击当前元素时候,才会触发事件
<!-- 只有当点击 div 时才执行 divClick,其它情况(如:冒泡、捕获等)都不执行 -->
<div class="inner" @click.self="divClick">
     <input type="button" value="按钮" @click="btnClick">
</div>
  • .once 只触发一次事件
<!-- 事件只执行一次,事件修饰符可组合使用 -->
<a href="http://www.baidu.com" @click.prevent.once="linkClick">有问题,先去百度</a>

Vue中双向数据绑定

  • v-model 指令:可以实现 表单元素和 Model 中数据的双向数据绑定
<!-- v-bind 只能实现数据的单向绑定,从 M 自动绑定到 V, 无法实现数据的双向绑定  -->
<input type="text" v-bind:value="msg" style="width:100%;">

<!-- 注意: v-model 只能运用在 表单元素中 -->
<!-- input(radio, text, address, email....)   select    checkbox   textarea   -->
<input type="text" style="width:100%;" v-model="msg">

Vue中使用样式

<!-- 一般用法 -->
<h1 class="red thin">我是一个很长很长的标题!!!</h1>

<!-- Vue中用法:使用数组 -->
<h1 v-bind:class="['red', 'thin']">我是一个很长很长的标题!!!</h1>
<h1 :class="['red', 'thin', isActive ? 'active' : '']">我是一个很长很长的标题!!!</h1>
<h1 :class="['red', 'thin', {'active': isActive}]">我是一个很长很长的标题!!!</h1>

<!-- Vue中用法:直接使用对象 -->
<h1 :class="{red: true, thin: true, active: true}">我是一个很长很长的标题!!!</h1>
<h1 :class="h1StyleObj">我是一个很长很长的标题!!!</h1>

<h1 :style="{'color': 'red', 'font-size': '40px'}">我是一个很长很长的标题!!!</h1>

过滤器

过滤器就是数据在输出前做最后一层的处理,即格式化输出。
常用在两个地方:{{ }} 或 v-bind: 中,用管道符("|")指示

  • 过滤器的定义语法:Vue.filter('过滤器的名称', function(){})
  • 过滤器调用时候的格式:{{ name | 过滤器的名称 }}
  1. 自定义 Vue 全局的过滤器
// 过滤器1:返回有效字符串(字符串格式化)
Vue.filter("ValidString", function(str, msg = "") {
  if (str == null || typeof str == "undefined" || str == "") {
      return msg;
  }
  // 去掉字符串头尾空格
  if (str.replace(/(^\s*)|(\s*$)/g, "") == "") {
      return msg;
  }
  return str;
}));

// 过滤器2:返回年月日字符串(时间格式化)
// format 给一个默认值,防止不传这个参数时 format = "undefined" 而报错
Vue.filter("dateFormatYMD", function(dateStr, format = "") {
  if (dateStr.length < 10) {
    return dateStr;
  }
  // 根据时间字符串,得到时间
  var date = new Date(dateStr);
  var y = date.getFullYear().toString().padStart(4, '0');
  var m = (date.getMonth() + 1).toString().padStart(2, '0');
  var d = date.getDate().toString().padStart(2, '0');

  if (format.toLowerCase() === 'yyyy-mm-dd') {
      // return y + '-' + m + '-' + d;
      return `${y}-${m}-${d}`;  // 模板字符串
  } else {
      var h = dt.getHours().toString().padStart(2, '0');
      var m = dt.getMinutes().toString().padStart(2, '0');
      var s = dt.getSeconds().toString().padStart(2, '0');
      return `${y}-${m}-${d} ${h}:${m}:${s}`;
  }
}));

<!-- 2.过滤器的使用 -->
{{ name | ValidString("暂无姓名") }}

{{ date | ValidString("暂无") | dateFormatYMD() }}
  1. 自定义 Vue 私有的过滤器
// 全局过滤器( app 和 app2 都能使用):返回有效字符串
Vue.filter("ValidString", function(str, msg = "") {
  if (str == null || typeof str == "undefined" || str == "") {
      return msg;
  }
  // 去掉字符串头尾空格
  if (str.replace(/(^\s*)|(\s*$)/g, "") == "") {
      return msg;
  }
  return str;
}));

// 创建 Vue 实例
var app = new Vue({
  el: '#app',
  data: {
      msg: ""
  },
  methods: {
      show () {
        console.log("show方法");
      },
      dismiss () {
        console.log("dismiss方法");
      }
  }
})

// 创建 Vue 实例
var app2 = new Vue({
  el: '#app2',
  data: {
      msg: ""
  },
  methods: {
      show () {
        console.log("show方法");
      },
      dismiss () {
        console.log("dismiss方法");
      }
  },
  filters: {  // 定义私有过滤器(只能 app2 使用)
      ValidString: function (str, msg = "") {
        if (str == null || typeof str == "undefined" || str == "") {
            return msg;
        }
        // 去掉字符串头尾空格
        if (str.replace(/(^\s*)|(\s*$)/g, "") == "") {
            return msg;
        }
        return str;
      }
  }
})

<!-- 过滤器的调用:采用的是就近原则,这里调用的是私有的 ValidString -->
{{ name | ValidString("暂无姓名") }}

监听输入框键盘回车事件

<!-- 监听键盘(所有键)抬起事件 -->
<input type="text" class="form-control" v-model="name" @keyup="nameEnter">

<!-- 监听“Enter键”抬起事件(可通过 按键修饰符 来控制) -->
<input type="text" class="form-control" v-model="name" @keyup.enter="nameEnter">
  • 按键修饰符
<!-- keyCode == 13(键盘码:键盘上每个按键都对应一个键盘码)时,调用 submit 方法 -->
<input type="text" @keyup.13="submit">

// Vue框架内定义的按键修饰符
<input type="text" @keyup.enter="submit">
<input type="text" @keyup.tab="submit">
<input type="text" @keyup.delete="submit">
<input type="text" @keyup.esc="submit">
... ... 

// 自定义按键修饰符(即给键盘码取别名)
Vue.config.keyCodes.f2 = 113;
<!-- 监听“F2键”抬起事件 -->
<input type="text" @keyup.113="submit">
<input type="text" @keyup.f2="submit">
  • 自定义指令(如:v-focus、v-color):输入框自动获取焦点
// 1.DOM操作实现
document.getElementById('search').focus();

<!-- 2.通过自定义指令来实现:v-focus (默认Vue没有帮我们实现这个指令,需要我们自己去实现)-->
<input type="text" id="search" v-focus v-color="'blue'">

// 使用  Vue.directive() 定义全局的指令  v-focus
// 参数1 :指令的名称(定义时不需要加 v- 前缀,调用的时候需要加)
// 参数2: 是一个对象,这个对象身上,有一些指令相关的函数,这些函数可以在特定的阶段,执行相关的操作
Vue.directive('focus',  {
  // 和JS行为相关的操作,最好在钩子函数(时机函数) inserted 中去执行,防止JS行为不生效
  // 当绑定元素插入到DOM中执行
  inserted: function (el) {
    // 聚焦元素
    el.focus();
  }
});


// 自定义一个设置字体颜色的指令(支持传参)
Vue.directive('color',  {
  // 和样式相关的操作,一般都在钩子函数(时机函数) bind 中去执行
  bind: function (el, binding) {
    el.style.color = binding.value;
  }
});

也可以定义局部指令,组件中接收一个directives的选项

// 定义私有(局部)指令
directives: {
  'focus': {
     // 指令的定义
     inserted: function (el) {
        // 聚焦元素
        el.focus();
     }
  }
}

常用鼠标、键盘事件

click:鼠标单击
dbclick:鼠标双击

mouseover:鼠标经过
mouseout:鼠标移开

keydown:键盘按下
keyup:键盘弹起

相关文章

网友评论

      本文标题:【前端】Vue.js 基础篇(上)

      本文链接:https://www.haomeiwen.com/subject/ywvgthtx.html