Vue.js框架笔记

Vue.js框架笔记

    • 1. 初识 Vue.js
        • 1. 遇见 Vue.js
            • 1.1 为什么要学习 Vue.js
            • 1.2 前端开发的复杂化
            • 1.3 Vuejs 特点
        • 2. 安装 Vuejs
            • 2.1 直接 CDN 引入
            • 2.2 下载和引入
            • 2.3 NPM 安装
            • 2.4 CLI 和 NPM 结合使用
        • 3. 体验 Vuejs
            • 3.1 Hello Vuejs
            • 3.2 Vue 显示列表
            • 3.3 实现计数器
        • 4. MVVM 架构
            • 4.1 data 和 Vue 对象的分离
            • 4.2 Vue 中的 MVVM
            • 4.3 创建Vue实例传入的 options
            • 4.4 Vue 的生命周期
    • 2. Vue 基础语法
        • 1. 插值语法
            • 1.1 `Mustache`语法
            • 1.2 `v-once`语法
            • 1.3 `v-html`语法
            • 1.4 `v-pre`语法
            • 1.5 `v-cloak`语法
        • 2. 绑定属性
            • 2.1 v-bind 介绍
            • 2.2 v-bind 基础
            • 2.3 v-bind 语法
            • 2.4 动态绑定 class
            • 2.5 动态绑定样式 style
        • 3. 计算属性
            • 3.1 计算属性的介绍
            • 3.2 计算属性的复杂操作
            • 3.3 计算属性的setter和getter
            • 3.4 计算属性的缓存
        • 4. 事件监听
            • 4.1 v-on介绍
            • 4.2 v-on基础
            • 4.3 v-on参数
            • 4.4 v-on修饰符
        • 5. 条件和循环
            • 5.1 条件渲染
            • 5.2 v-show指令
            • 5.3 v-for指令
            • 5.4 组件的`key属性`
            • 5.5 检测数组更新
        • 6. 表单绑定
            • 6.1 基本使用
            • 6.2 v-model原理
            • 6.3 v-model 绑定其他属性
            • 6.4 值绑定
            • 6.5 修饰符
    • 3. 组件化开发
        • 1. 认识组件化
            • 1.1 什么是组件化
            • 1.2 Vue组件化思想
        • 2. 组件化基础
          • 1. 注册组件
            • 1.1 注册的基本步骤
            • 1.2 注册组件步骤解析
          • 2. 全局和局部组件
          • 3. 父组件和子组件
          • 4. 注册组件语法糖
          • 5. 模板的分离写法
          • 6. 组件中的数据
            • 6.1 组件访问Vue实例数据
            • 6.2 组件数据的存放
            • 6.3 组件数据为什么是一个函数?
        • 3. 组件中数据传递
          • 1. 父级向子级传递
            • 1.1 props基本用法
            • 1.2 props数据验证
            • 1.3 props中的驼峰标识
          • 2. 子级向父级传递
          • 3. 父子组件之间的数据访问
          • 4. 父子组件的访问方式
            • 4.1 `$children`
            • 4.2 `$refs`
            • 4.3 `$parent`
          • 5. 非父子组件通信
        • 4. 插槽slot
          • 1. 为什么使用slot
          • 2. 如何封装
          • 3. slot的基本使用
          • 4. slot的具名插槽
        • 5. slot作用域插槽
          • 1. 编译作用域
          • 2. slot作用域插槽使用
    • 4. 模块化开发
        • 1. 为什么要模块化
          • 1. JavaScript原始功能
          • 2. 匿名函数的解决方案
          • 3. 使用模块作为出口
        • 2. CommonJS
        • 3. ES6的export指令
          • 1. export基本使用
          • 2. 导出函数或类
          • 3. export default
        • 4. ES6的import指令
          • 1. import使用
    • 5. Vue CLI 详解
        • 1. Vue CLI
            • 1. Vue CLI是什么?
            • 2. Vue CLI使用前提 - Node
            • 3. Vue CLI使用前提 - Webpack
            • 4. Vue CLI的使用
        • 2. Vue CLI2的使用
            • 1. Vue CLI2详解
            • 2. 目录结构详解
            • 3. Runtime-Compiler和Runtime-only的区别
            • 4. render和template
            • 5. Vue程序运行过程
            • 6. render函数的使用
            • 7. npm run build
            • 8. npm run dev
            • 9. 修改配置:webpack.base.conf.js起别名
        • 3. Vue CLI3的使用
            • 1. 认识Vue CLI3
            • 2. 目录结构详解
            • 3. Vue cli3 配置
            • 4. 自定义配置:起别名
    • 6. vue-router
        • 1. 认识路由
            • 1. 什么是路由
            • 2. 后端路由阶段
            • 3. 前端路由阶段
        • 2. 前端路由的规则
            • 1. URL的hash
            • 2. HTML5 的 history 模式
        • 3. vue-router 基础
            • 1. 认识 vue-router
            • 2. 安装和使用 vue-router
            • 3. 创建 router 实例
            • 4. 挂载到 Vue 实例中
            • 5. vue-router 基本使用
        • 4. vue-router 细节补充
            • 1. 路由的默认路径
            • 2. HTML5的History模式
            • 3. router-link补充
            • 4. 修改linkActiveClass
            • 5. 路由代码跳转
            • 6. 动态路由
        • 5. 路由的懒加载
            • 1. 认识路由懒加载
            • 2. 路由懒加载的效果
            • 3. 懒加载的方式
        • 6. 路由嵌套使用
            • 1. 认识嵌套路由
            • 2. 嵌套路由实现
            • 3. 嵌套默认路径
        • 7. 路由传递参数
            • 1. 准备工作
            • 2. 传递参数的方式
            • 3. 传递参数方式一: ``
            • 4. 传递参数方式二: `JavaScript代码`
            • 5. 获取参数
            • 6. `$route`和`$router`是有区别的
        • 8. 路由导航守卫
            • 1. 为什么使用导航守卫?
            • 2. 导航守卫使用
        • 9. keep-alive
        • 10. TabBar练习
            • 1. TabBar实现思路
            • 2. 代码实现
    • 6. Vuex 详解
        • 1. 认识 Vuex
            • 1. Vuex是做什么的
            • 2. 管理什么状态
            • 3. 单界面的状态管理
            • 4. 单界面状态管理的实现
            • 5. 多界面状态管理
            • 6. Vuex状态管理图例
        • 2. Vuex基本使用
            • 1. 简单的案例
            • 2. 挂载到Vue实例中
            • 3. 使用Vuex的count
    • 7. Vuex核心概念
        • 1. state
            • State单一状态树
        • 2. Getters
            • Getters基本使用
            • Getters作为参数和传递参数
        • 3. Mutation
            • Mutation状态更新
            • Mutation传递参数
            • Mutation提交风格
            • Mutation响应规则
            • Mutation常量类型 – 概念
            • Mutation常量类型 – 代码
            • Mutation同步函数
        • 4. Action
            • Action基本定义
            • Action的分发
            • Action返回的Promise
        • 5. Module
            • 认识Vuex的Module
            • Module的局部状态
            • Module的Actions写法
    • 8. 网络模块封装
        • 1. 网络模块的选择
            • 1. 选择 `Ajax`
            • 2. 选择 `jQuery-Ajax`
            • 3. 选择 `Vue-resource`
            • 4. 选择 `axios`
        • 2. jsonp的封装
            • jsonp
            • JSONP封装
        • 3. axios的使用
            • 1. 认识 `axios`
            • 2. 发送基本请求
        • 4. axios的实例
            • axios的实例
            • axios 封装
        • 5. 拦截器
            • 1. 如何使用拦截器?
            • 2. 拦截器中都做什么呢?
    • 总结

1. 初识 Vue.js

1. 遇见 Vue.js

1.1 为什么要学习 Vue.js
  • 组件化
    • 其中以 React 的组件化最为彻底,甚至可以到函数级别的原子组件,高度的组件化可以是我们的工程易于维护、易于组合拓展
  • 天然分层: jQuery 时代的代码大部分情况下是面条代码,耦合严重,现代框架不管是 MVCMVP还是MVVM 模式都能帮助我们进行分层,代码解耦更易于读写
  • 生态: 现在主流前端框架都自带生态,不管是数据流管理架构还是 UI 库都有成熟的解决方案
1.2 前端开发的复杂化
  • Vue (读音 /vjuː/,类似于 view),不要读错
  • Vue是一个渐进式的框架
    • 渐进式意味着你可以将Vue作为你应用的一部分嵌入其中,带来更丰富的交互体验
    • 或者如果你希望将更多的业务逻辑使用Vue实现,那么Vue的核心库以及其生态系统
    • 比如Core+Vue-router+Vuex,也可以满足你各种各样的需求
1.3 Vuejs 特点
  • Vue有很多特点和Web开发中常见的高级功能
    • 解耦视图和数据
    • 可复用的组件
    • 前端路由技术
    • 状态管理
    • 虚拟DOM

2. 安装 Vuejs

2.1 直接 CDN 引入
  • 可以选择引入开发环境版本还是生产环境版本
 
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js">script>

<script src="https://cdn.jsdelivr.net/npm/vue">script>
2.2 下载和引入
  • 开发环境 https://vuejs.org/js/vue.js
  • 生产环境 https://vuejs.org/js/vue.min.js
2.3 NPM 安装
2.4 CLI 和 NPM 结合使用

3. 体验 Vuejs

3.1 Hello Vuejs
  • 创建Vue对象的时候,传入了一些options:{}
    • {}中包含了el属性:该属性决定了这个Vue对象挂载到哪一个元素上,很明显,我们这里是挂载到了idapp的元素上
    • {}中包含了data属性:该属性中通常会存储一些数据
      • 这些数据可以是我们直接定义出来的,比如像message这样
      • 也可能是来自网络,从服务器加载的
  • 浏览器执行代码的流程:
    • 执行显然出对应的HTML
    • 执行创建Vue实例,并且对原HTML进行解析和修改
  • 并且,目前我们的代码是可以做到响应式
<div id="app">{{message}}div>
<script src="../vue.js" charset="utf-8">script>
<script type="text/javascript">
  // 编程范式:声明式编程
  const app = new Vue({
    el:'#app', // 用于挂载要管理的元素
    data:{ // 定义数据
      message:'hello Vue.js'
    }
  })
script>
3.2 Vue 显示列表
  • 展示一个更加复杂的数据:数据列表。
    • 比如我们现在从服务器请求过来一个列表
    • 希望展示到HTML
  • HTML代码中,使用v-for指令
  • 不需要在JavaScript代码中完成DOM的拼接相关操作
  • 更重要的是,它还是响应式
    • 也就是说,当我们数组中的数据发生改变时,界面会自动改变
<div id="app">
        <ul>
            <li v-for="item in movies">{{item}}li>
        ul>
    div>

    <script src="../vue.js">script>
    <script>
        const app = new Vue({
            el: '#app',
            data: {
                message: '你好啊',
                movies: ['星际穿越', '大话西游', '少年派', '盗梦空间']
            }
        })
    script>
3.3 实现计数器
  • 新的属性:methods,该属性用于在Vue对象中定义方法。
  • 新的指令:@click, 该指令用于监听某个元素的点击事件,并且需要指定当发生点击时,执行的方法(方法通常是methods中定义的方法)
<div id="app">
      <h1>计数器:{{count}}h1>
      <button type="button" name="button" v-on:click='jia'>+button>
      <button type="button" name="button" @click='jian'>-button>
    div>
    <script src="../vue.js" charset="utf-8">script>
    <script type="text/javascript">
      // 编程范式: 声明式编程
      const app = new Vue({
        el:'#app', // 用于挂载要管理的元素
        data:{ // 定义数据
          count:0
        },
        methods:{
          jia:function(){
            this.count++;
          },
          jian:function(){
            this.count--;
          }
        }
      })
    script>

4. MVVM 架构

Vue.js框架笔记_第1张图片

4.1 data 和 Vue 对象的分离
  • 计数器的MVVM
    • 我们的计数器中就有严格的MVVM思想
      • View依然是我们的DOM
      • Model就是我们我们抽离出来的obj
      • ViewModel就是我们创建的Vue对象实例
    • 它们之间如何工作呢?
      • 首先ViewModel通过Data Bindingobj中的数据实时的在DOM中显示
      • 其次ViewModel通过DOM Listener来监听DOM事件,并且通过methods中的操作,来改变obj中的数据
  • 有了Vue帮助我们完成VueModel层的任务,在后续的开发,我们就可以专注于数据的处理,以及DOM的编写工作
4.2 Vue 中的 MVVM
  • View层:
    • 视图层
    • 在我们前端开发中,通常就是DOM层。
    • 主要的作用是给用户展示各种信息。
  • Model层:
    • 数据层
    • 数据可能是我们固定的死数据,更多的是来自我们服务器,从网络上请求下来的数据。
    • 在我们计数器的案例中,就是后面抽取出来的obj,当然,里面的数据可能没有这么简单。
  • VueModel层:
    • 视图模型层
    • 视图模型层是ViewModel沟通的桥梁。
    • 一方面它实现了Data Binding,也就是数据绑定,将Model的改变实时的反应到View
    • 另一方面它实现了DOM Listener,也就是DOM监听,当DOM发生一些事件(点击、滚动、touch等)时,可以监听到,并在需要的情况下改变对应的Data
4.3 创建Vue实例传入的 options
  • 我们在创建Vue实例的时候,传入了一个对象options
  • 这个options中可以包含哪些选项呢?
    • 详细解析: https://cn.vuejs.org/v2/api/#%E9%80%89%E9%A1%B9-%E6%95%B0%E6%8D%AE
  • 目前掌握这些选项:
    • el:
      • 类型:string | HTMLElement
      • 作用:决定之后Vue实例会管理哪一个DOM
    • data:
      • 类型:Object | Function (组件当中data必须是一个函数)
      • 作用:Vue实例对应的数据对象
    • methods:
      • 类型:{ [key: string]: Function }
      • 作用:定义属于Vue的一些方法,可以在其他地方调用,也可以在指令中使用
4.4 Vue 的生命周期
  • https://vue.docschina.org/images/lifecycle.png

2. Vue 基础语法

1. 插值语法

1.1 Mustache语法
  • 如何将data中的文本数据,插入到HTML中呢?
    • 我们已经学习过了,可以通过Mustache语法(也就是双大括号)
    • Mustache: 胡子/胡须.
  • 我们可以像下面这样来使用,并且数据是响应式
<div id="app">
  <h2>{{message}}h2>
  <h2>{{message}}, 李银河!h2>

  
  <h2>{{firstName + lastName}}h2>
  <h2>{{firstName + ' ' + lastName}}h2>
  <h2>{{firstName}} {{lastName}}h2>
  <h2>{{counter * 2}}h2>
div>

<script src="../../vue.js">script>
<script>
  const app = new Vue({
    el: '#app',
    data: {
      message: '你好啊',
      firstName: 'kobe',
      lastName: 'bryant',
      counter: 100
    }
  })
script>
1.2 v-once语法
  • 在某些情况下,我们可能不希望界面随意的跟随改变
    • 这个时候,我们就可以使用一个Vuev-once指令
  • 该指令后面不需要跟任何表达式(比如之前的v-for后面是由跟表达式的)
  • 该指令表示元素和组件只渲染一次,不会随着数据的改变而改变
<div id="app">
  <h2>{{message}}h2>
  <h2 v-once>{{message}}h2>
div>

<script src="../../vue.js">script>
<script>
  const app = new Vue({
    el: '#app',
    data: {
      message: '你好啊'
    }
  })
script>

Vue.js框架笔记_第2张图片

1.3 v-html语法
  • 某些情况下,我们从服务器请求到的数据本身就是一个HTML代码
    • 如果我们直接通过{{}}来输出,会将HTML代码也一起输出
    • 但是我们可能希望的是按照HTML格式进行解析,并且显示对应的内容
  • 如果我们希望解析出HTML展示
    可以使用v-html指令
    - 该指令后面往往会跟上一个string类型
    - 会将stringhtml解析出来并且进行渲染
<div id="app">
  <h2>{{url}}h2>
  <h2 v-html="url">h2>
div>

<script src="../../vue.js">script>
<script>
  const app = new Vue({
    el: '#app',
    data: {
      message: '你好啊',
      url: '百度一下'
    }
  })
script>

Vue.js框架笔记_第3张图片 ###### 1.4 v-text语法

  • v-text作用和Mustache比较相似:都是用于将数据显示在界面中
  • v-text通常情况下,接受一个string类型
  • v-text不够灵活,会将标签中的文本内容覆盖
<div id="app">
  <h2>{{message}}, Vue.js!h2>
  <h2 v-text="message">, Vue.js!h2>
div>

<script src="../../vue.js">script>
<script>
  const app = new Vue({
    el: '#app',
    data: {
      message: '你好啊'
    }
  })
script>

Vue.js框架笔记_第4张图片

1.4 v-pre语法
  • v-pre用于跳过这个元素和它子元素的编译过程,用于显示原本的Mustache语法
  • 比如下面的代码:
    • 第一个h2元素中的内容会被编译解析出来对应的内容
    • 第二个h2元素中会直接显示{{message}}
<div id="app">
  <h2>{{message}}h2>
  <h2 v-pre>{{message}}h2>
div>

<script src="../../vue.js">script>
<script>
  const app = new Vue({
    el: '#app',
    data: {
      message: '你好啊'
    }
  })
script>

Vue.js框架笔记_第5张图片

1.5 v-cloak语法
  • 在网络不佳或者加载js卡顿情况下,我们浏览器可能会直接显然出未编译的Mustache标签
  • Vue实例加载出来的时候,再显示html
  • cloak: 斗篷
<style>
  [v-cloak] {
    display: none;
  }
style>
<div id="app" v-cloak>
  <h2>{{message}}h2>
div>

<script src="../../vue.js">script>
<script>
  // 在vue解析之前, div中有一个属性v-cloak
  // 在vue解析之后, div中没有一个属性v-cloak
  setTimeout(function () {
    const app = new Vue({
      el: '#app',
      data: {
        message: '你好啊'
      }
    })
  }, 1000)
script>

2. 绑定属性

2.1 v-bind 介绍
  • 除了内容需要动态来决定外,某些属性我们也希望动态来绑定。
    • 比如动态绑定a元素的href属性
    • 比如动态绑定img元素的src属性
  • 这个时候,我们可以使用v-bind指令:
    • 作用:动态绑定属性
    • 缩写::
    • 预期:any (with argument) | Object (without argument)
    • 参数:attrOrProp (optional)
2.2 v-bind 基础
  • v-bind用于绑定一个或多个属性值,或者向另一个组件传递props
  • 在开发中,有哪些属性需要动态进行绑定呢?
    • 还是有很多的,比如图片的链接src、网站的链接href、动态绑定一些样式等等
  • 比如通过Vue实例中的data绑定元素的srchref
<div id="app">
  
  
  
  <img v-bind:src="imgURL" alt="">
  <a v-bind:href="aHref">百度一下a>
  

  
  <img :src="imgURL" alt="">
  <a :href="aHref">百度一下a>
div>

<script src="../../vue.js">script>
<script>
  const app = new Vue({
    el: '#app',
    data: {
      message: '你好啊',
      imgURL: 'https://img11.360buyimg.com/mobilecms/s350x250_jfs/t1/20559/1/1424/73138/5c125595E3cbaa3c8/74fc2f84e53a9c23.jpg!q90!cc_350x250.webp',
      aHref: 'http://www.baidu.com'
    }
  })
script>
2.3 v-bind 语法
  • v-bind有一个对应的语法糖,也就是简写方式
    • 在开发中,我们通常会使用语法糖的形式,因为这样更加简洁
  • 简写方式如下:
<div id="app">
	<a :href="link">Vue.js官网a>
	<img :src="logoURL" alt="">
div>
2.4 动态绑定 class
  • 很多时候,我们希望动态的来切换class,比如:
    • 当数据为某个状态时,字体显示红色。
    • 当数据另一个状态时,字体显示黑色。
  • 绑定class有两种方式:
    • 对象语法
    • 数组语法
  • 绑定方式:对象语法
    • 对象语法的含义是:class后面跟的是一个对象
  • 对象语法有下面这些用法:
用法一:直接通过{}绑定一个类
<h2 :class="{'active': isActive}">Hello Worldh2>

用法二:也可以通过判断,传入多个值
<h2 :class="{'active': isActive, 'line': isLine}">Hello Worldh2>

用法三:和普通的类同时存在,并不冲突
注:如果isActive和isLine都为true,那么会有title/active/line三个类
<h2 class="title" :class="{'active': isActive, 'line': isLine}">Hello Worldh2>

用法四:如果过于复杂,可以放在一个methods或者computed中
注:classes是一个计算属性
<h2 class="title" :class="classes">Hello Worldh2>
  • 绑定方式:数组语法
    • 数组语法的含义是:class后面跟的是一个数组
  • 数组语法有下面这些用法:
用法一:直接通过{}绑定一个类
<h2 :class="['active']">Hello Worldh2>

用法二:也可以传入多个值
<h2 :class=“[‘active’, ‘line']">Hello Worldh2>

用法三:和普通的类同时存在,并不冲突
注:会有title/active/line三个类
<h2 class="title" :class=“[‘active’, 'line']">Hello Worldh2>

用法四:如果过于复杂,可以放在一个methods或者computed中
注:classes是一个计算属性
<h2 class="title" :class="classes">Hello Worldh2>
2.5 动态绑定样式 style
  • 我们可以利用v-bind:style来绑定一些CSS内联样式
  • 在写CSS属性名的时候,比如font-size
    • 我们可以使用驼峰式 (camelCase) fontSize
    • 短横线分隔 (kebab-case,记得用单引号括起来) ‘font-size’
  • 绑定class有两种方式:
    • 对象语法
    • 数组语法
  • 绑定方式:对象语法
    • style后面跟的是一个对象类型
      • 对象的keyCSS属性名称
      • 对象的value是具体赋的值,值可以来自于data中的属性
<h2 :style="{color: currentColor, fontSize: fontSize + 'px'}">{{messages}}h2>
  • 绑定方式:数组语法
    • style后面跟的是一个数组类型
      • 多个值以,分割即可
<div v-bind:style="[baseStyles, overridingStyles]">div>

3. 计算属性

3.1 计算属性的介绍
  • 在模板中可以直接通过插值语法显示一些data中的数据。
  • 但是在某些情况,我们可能需要对数据进行一些转化后再显示,或者需要将多个数据结合起来进行显示
    • 比如我们有firstNamelastName两个变量,我们需要显示完整的名称
    • 但是如果多个地方都需要显示完整的名称,我们就需要写多个{{firstName}} {{lastName}}
  • 我们可以将上面的代码换成计算属性:
    • 计算属性是写在实例的computed选项中的
<div id="app">
	<h2>{{firstName}}{{lastName}}h2>
div>
<script>
	const vm = new Vue({
		el: '#app',
		data: {
			firstName: 'Kobe',
			lastName: 'Bryant'
		}
	})
<script>
  • 替换为:
<div id="app">
	<h2>{{fullName}}h2>
div>
<script>
	const vm = new Vue({
		el: '#app',
		computed: {
			fullName(){
				return this.firstName + '' + this.lastName
			}
		}
	})
<script>
3.2 计算属性的复杂操作
<div id="app">
  <h2>总价格: {{totalPrice}}h2>
div>

<script src="../../vue.js">script>
<script>
  const app = new Vue({
    el: '#app',
    data: {
      books: [
        {id: 110, name: 'Unix编程艺术', price: 119},
        {id: 111, name: '代码大全', price: 105},
        {id: 112, name: '深入理解计算机原理', price: 98},
        {id: 113, name: '现代操作系统', price: 87},
      ]
    },
    computed: {
      totalPrice: function () {
        let result = 0
        for (let i=0; i < this.books.length; i++) {
          result += this.books[i].price
        }
        return result
      }
    }
  })
script>
3.3 计算属性的setter和getter
  • 每个计算属性都包含一个getter和一个setter
    在上面的例子中,我们只是使用getter来读取
    在某些情况下,你也可以提供一个setter方法(不常用)
    在需要写setter的时候,代码如下:
computed: {
  fullName: {
    set: function(newValue) {
      // console.log('-----', newValue);
      const names = newValue.split(' ');
      this.firstName = names[0];
      this.lastName = names[1];
    },
    get: function () {
      return this.firstName + ' ' + this.lastName
    }
  },
}
3.4 计算属性的缓存
  • methodscomputed区别
    • 计算属性computed会进行缓存,如果多次使用时,计算属性只会调用一次
    • 而方法属性methods会多次调用
<div id="app">
	<div>{{fullName}}div>
	<div>{{fullName}}div>
	<div>{{fullName}}div>
	<div>{{getFullName()}}div>
	<div>{{getFullName()}}div>
	<div>{{getFullName()}}div>
div>
computed: {
	fullName(){
		console.log('执行fullName的计算属性');
		return this.firstName + ' ' + this.lastName;
	}
},
methods: {
	getFullName(){
		console.log('执行getFullName的方法');
		return this.firstName + ' ' + this.lastName;
	}
}

4. 事件监听

4.1 v-on介绍
  • 在前端开发中,我们需要经常和用于交互
    • 这个时候,我们就必须监听用户发生的时间,比如点击、拖拽、键盘事件等等
    • Vue中使用v-on指令监听事件
  • v-on介绍
    • 作用:绑定事件监听器
    • 缩写:@
    • 预期:Function | Inline Statement | Object
    • 参数:event
4.2 v-on基础
  • 这里,我们用一个监听按钮的点击事件,来简单看看v-on的使用
    • 下面的代码中,我们使用了v-on:click="counter++”
    • 另外,我们可以将事件指向一个在methods中定义的函数
<div id="app">
  <h2>点击次数: {{counter}}h2>
  <button v-on:click="counter++">按钮点击button>
  <button v-on:click="btnClick">按钮点击button>
div>
<script>
  const app = new Vue({
    el: '#app',
    data: {
      counter: 0
    },
    methods: {
      btnClick(){
      	this.counter++
      }
    }
  })
script>
  • 注:v-on也有对应的语法糖:
    • v-on:click可以写成@click
<div id="app">
  <h2>点击次数: {{counter}}h2>
  <button @click="counter++">按钮点击button>
  <button @click="btnClick">按钮点击button>
div>
4.3 v-on参数
  • 当通过methods中定义方法,以供@click调用时,需要注意参数问题:
  • 情况一:如果该方法不需要额外参数,那么方法后的()可以不添加
    • 注意:如果方法本身中有一个参数,那么会默认将原生事件event参数传递进去
  • 情况二:如果需要同时传入某个参数,同时需要event时,可以通过$event传入事件
<div id="app">
  <h2>点击次数: {{counter}}h2>
  <button @click="handleAdd">+1button>
  <button @click="handleAddTen(10,$event)">+10button>
div>
methods: {
	handleAdd(event){
		console.log(event);
		this.counter++
	},
	handleAddTen(count,event){
		console.log(event);
		this.counter += 10;
	}
}
4.4 v-on修饰符
  • 在某些情况下,我们拿到event的目的可能是进行一些事件处理
  • Vue提供了修饰符来帮助我们方便的处理一些事件:
    • .stop - 调用 event.stopPropagation()
    • .prevent - 调用 event.preventDefault()
    • .{keyCode | keyAlias} - 只当事件是从特定键触发时才触发回调
    • .native - 监听组件根元素的原生事件
    • .once - 只触发一次回调
1. 停止冒泡
<button @click.stop="doThis">button>
2. 阻止默认行为
<button @click.prevent="doThis">button>
3. 阻止默认行为,没有表达式
<form @submit.prevent>form>
4. 串联修饰符
<button @click.stop.prevent="doThis">button>
5. 键修饰符,键别名
<input @keyup.enter="onEnter">
6. 键修饰符,键代码
<input @keyup.13="onEnter">
7. 点击回调只会触发一次
<button @click.once="doThis">button>

5. 条件和循环

5.1 条件渲染
  • v-ifv-else-ifv-else
    • 这三个指令与JavaScript的条件语句ifelseelse if类似。
    • Vue的条件指令可以根据表达式的值在DOM中渲染或销毁元素或组件
  • 简单的案例演示:
<div id="app">
  <h2 v-if="score>=90">优秀h2>
  <h2 v-else-if="score>=80">良好h2>
  <h2 v-else-if="score>=60">及格h2>
  <h2 v-else>不及格h2>
div>
<script>
  const app = new Vue({
    el: '#app',
    data: {
      score: 99
    }
  })
script>
  • v-if的原理:
    • v-if后面的条件为false时,对应的元素以及其子元素不会渲染
    • 也就是根本没有不会有对应的标签出现在DOM
5.2 v-show指令
  • v-show的用法和v-if非常相似,也用于决定一个元素是否渲染:
  • v-ifv-show对比
  • v-ifv-show都可以决定一个元素是否渲染,那么开发中我们如何选择呢?
    • v-if当条件为false时,压根不会有对应的元素在DOM
    • v-show当条件为false时,仅仅是将元素的display属性设置为none而已。
  • 开发中如何选择呢?
    • 当需要在显示与隐藏之间切片很频繁时,使用v-show
    • 当只有一次切换时,通过使用v-if
<div id="app">
  <button @click="toggle">切换显示button>
  <h2 v-show="isShow">我要不要显示呢h2>
div>

<script src="../../vue.js">script>
<script>
  const app = new Vue({
    el: '#app',
    data: {
      isShow: true
    },
    methods: {
    	toggle() {
    		this.isShow = !this.isShow
    	}
    }
  })
script>
5.3 v-for指令
  • 当我们有一组数据需要进行渲染时,我们就可以使用v-for来完成
    • v-for的语法类似于JavaScript中的for循环
    • 格式如下:item in items的形式
  • 我们来看一个简单的案例:
  • 如果在遍历的过程中不需要使用索引值
    • v-for="movie in movies"
    • 依次从movies中取出movie,并且在元素的内容中,我们可以使用Mustache语法,来使用movie
  • 如果在遍历的过程中,我们需要拿到元素在数组中的索引值呢?
    • 语法格式:v-for=(item, index) in items
    • 其中的index就代表了取出的item在原数组的索引值
<div id="app">
	<ul>
		<li v-for="item in movies">{{item}}li>
		<li v-for="(movie,index) in movies">{{index+1}}.{{movie}}li>
	ul>
div>
<script>
	const app = new Vue({
		el: '#app',
		data: {
			movies: [
				'星际穿越','盗墓笔记','大话西游','少年派'
			]
		}
	})
script>
  • v-for可以用户遍历对象
    • 比如某个对象中存储着你的个人信息,我们希望以列表的形式显示出来
<div id="app">
	<ul>
		<li v-for="(value,key,index) in info">{{value}}-{{key}}-{{index}}li>
	ul>
div>
<script>
	const app = new Vue({
		el: '#app',
		data: {
			info: [
				name: 'xxx',
				age: 18,
				height: 1.80
			]
		}
	})
script>
5.4 组件的key属性
  • 官方推荐我们在使用v-for时,给对应的元素或组件添加上一个:key属性
  • 为什么需要这个key属性呢(了解)?
    • 这个其实和Vue的虚拟DOMDiff算法有关系。
    • 这里我们借用React’s diff algorithm中的一张图来简单说明一下:
  • 当某一层有很多相同的节点时,也就是列表节点时,我们希望插入一个新的节点
    • 我们希望可以在B和C之间加一个F,Diff算法默认执行起来是这样的。
    • 即把C更新成F,D更新成C,E更新成D,最后再插入E,是不是很没有效率?
  • 所以我们需要使用key来给每个节点做一个唯一标识
    • Diff算法就可以正确的识别此节点
    • 找到正确的位置区插入新的节点
  • 所以一句话,key的作用主要是为了高效的更新虚拟DOM
    Vue.js框架笔记_第6张图片
5.5 检测数组更新
  • 因为Vue响应式的,所以当数据发生变化时,Vue会自动检测数据变化,视图会发生对应的更新
  • Vue中包含了一组观察数组编译的方法,使用它们改变数组也会触发视图的更新
methods: {
	updateData: function(){
		// 响应式数组方法
		// 1. push方法
		this.names.push('xxx','zs')
		// 2. pop方法
		this.names.pop()
		// 3. unshift方法
		this.names.unshift('xxx','zs')
		// 4. shift方法
		this.names.shift()
		// 5. splice方法
		// 传递一个参数(index):将对应index,以及后面的所有数据删除掉
		this.names.splice(2)
		// 6. sort排序数据
		this.names.sort()
		// 7. reverse反转数据
		this.names.reverse()

		// 注意: 通过索引值修改数组中的元素(不可响应式)
        this.letters[0] = 'bbbbbb';
        // 通过以下方法
        this.letters.splice(0, 1, 'bbbbbb')
        // set(要修改的对象, 索引值, 修改后的值)
        Vue.set(this.letters, 0, 'bbbbbb')		

6. 表单绑定

6.1 基本使用
  • 表单控件在实际开发中是非常常见的。特别是对于用户信息的提交,需要大量的表单。
  • Vue中使用v-model指令来实现表单元素和数据的双向绑定
  • 案例的解析:
    • 当我们在输入框输入内容时
    • 因为input中的v-model绑定了message,所以会实时将输入的内容传递给messagemessage发生改变。
    • message发生改变时,因为上面我们使用Mustache语法,将message的值插入到DOM中,所以DOM会发生响应的改变。
    • 所以,通过v-model实现了双向的绑定。
  • 当然,我们也可以将v-model用于textarea元素
<div id="app">
  <input type="text" v-model="message">
  {{message}}
div>

<script src="../../vue.js">script>
<script>
  const app = new Vue({
    el: '#app',
    data: {
      message: '你好啊'
    }
  })
script>

在这里插入图片描述

6.2 v-model原理
  • v-model其实是一个语法糖,它的背后本质上是包含两个操作:
    • v-bind绑定一个value属性
    • v-on指令给当前元素绑定input事件
<input type="text" v-model="message">
等于下面代码
<input type="text" :value="message" @input="message = $event.target.value">
6.3 v-model 绑定其他属性
  • v-model: radio
    • 当存在多个单选框时
<div id="app">
  <label for="male">
    <input type="radio" id="male" value="" v-model="sex">label>
  <label for="female">
    <input type="radio" id="female" value="" v-model="sex">label>
  <h2>您选择的性别是: {{sex}}h2>
div>

<script src="../../vue.js">script>
<script>
  const app = new Vue({
    el: '#app',
    data: {
      message: '你好啊',
      sex: '女'
    }
  })
script>
  • v-model: checkbox
    • 复选框分为两种情况:单个勾选框多个勾选框
      • 单个勾选框
        • v-model即为布尔值
        • 此时inputvalue并不影响v-model的值
      • 多个复选框
        • 当是多个复选框时,因为可以选中多个,所以对应的data中属性是一个数组
        • 当选中某一个时,就会将inputvalue添加到数组中
<div id="app">
	
	<label for="check">
		<input type="checkbox" id="check" v-model="checked">同意协议
	label>
  	<p>是否选中: {{checked}}p>

	
	<label><input type="checkbox" v-model="hobbies" value="篮球">篮球label>
	<label><input type="checkbox" v-model="hobbies" value="足球">足球label>
	<label><input type="checkbox" v-model="hobbies" value="台球">台球label>
	<p>您选中的爱好: {{hobbies}}p>
div>
<script>
  const app = new Vue({
    el: '#app',
    data: {
      checked: false, // 单选框
      hobbies: [], // 多选框
  })
script>
  • v-model:select
    • checkbox一样,select也分单选和多选两种情况
    • 单选:只能选中一个值。
      • v-model绑定的是一个值。
      • 当我们选中option中的一个时,会将它对应的value赋值到mySelect
    • 多选:可以选中多个值。
      • v-model绑定的是一个数组。
      • 当选中多个值时,就会将选中的option对应的value添加到数组mySelects

<select name="abc" v-model="mySelect">
  <option value="苹果">苹果option>
  <option value="香蕉">香蕉option>
  <option value="榴莲">榴莲option>
  <option value="葡萄">葡萄option>
select>
<h2>您选择的水果是: {{mySelect}}h2>


<select name="abc" v-model="mySelects" multiple>
  <option value="苹果">苹果option>
  <option value="香蕉">香蕉option>
  <option value="榴莲">榴莲option>
  <option value="葡萄">葡萄option>
select>
<h2>您选择的水果是: {{mySelects}}h2>

<script>
  const app = new Vue({
    el: '#app',
    data: {
      mySelect: '香蕉',
      mySelects: []
    }
  })
script>
6.4 值绑定
  • 值绑定就是动态的给value赋值而已:
    • 我们前面的value中的值,可以回头去看一下,都是在定义input的时候直接给定的
    • 但是真实开发中,这些input的值可能是从网络获取或定义在data中的
    • 所以我们可以通过v-bind:value动态的给value绑定值
  <label v-for="item in originHobbies" :for="item">
    <input type="checkbox" :value="item" :id="item" v-model="hobbies">{{item}}
  label>
  <script>
	  const app = new Vue({
	    el: '#app',
	    data: {
	      hobbies: [], // 多选框,
	      originHobbies: ['篮球', '足球', '乒乓球', '羽毛球', '台球', '高尔夫球']
	    }
	  })
script>
6.5 修饰符
  • lazy修饰符:
    • 默认情况下,v-model默认是在input事件中同步输入框的数据的
    • 也就是说,一旦有数据发生改变对应的data中的数据就会自动发生改变
    • lazy修饰符可以让数据在失去焦点或者回车时才会更新
  • number修饰符:
    • 默认情况下,在输入框中无论我们输入的是字母还是数字,都会被当做字符串类型进行处理
    • 但是如果我们希望处理的是数字类型,那么最好直接将内容当做数字处理
    • number修饰符可以让在输入框中输入的内容自动转成数字类型
  • trim修饰符:
    • 如果输入的内容首尾有很多空格,通常我们希望将其去除
    • trim修饰符可以过滤内容左右两边的空格

<input type="text" v-model.lazy="message">
<h2>{{message}}h2>


<input type="number" v-model.number="age">
<h2>{{age}}-{{typeof age}}h2>


<input type="text" v-model.trim="name">
<h2>您输入的名字:{{name}}h2>

3. 组件化开发

1. 认识组件化

1.1 什么是组件化
  • 人面对复杂问题的处理方式:
    • 任何一个人处理信息的逻辑能力都是有限的
    • 所以,当面对一个非常复杂的问题时,我们不太可能一次性搞定一大堆的内容
    • 但是,我们人有一种天生的能力,就是将问题进行拆解
    • 如果将一个复杂的问题,拆分成很多个可以处理的小问题,再将其放在整体当中,你会发现大的问题也会迎刃而解
  • 组件化也是类似的思想:
    • 如果我们将一个页面中所有的处理逻辑全部放在一起,处理起来就会变得非常复杂,而且不利于后续的管理以及扩展
    • 但如果,我们讲一个页面拆分成一个个小的功能块,每个功能块完成属于自己这部分独立的功能,那么之后整个页面的管理和维护就变得非常容易了
      Vue.js框架笔记_第7张图片
      Vue.js框架笔记_第8张图片
  • 我们将一个完整的页面分成很多个组件
  • 每个组件都用于实现页面的一个功能块
  • 而每一个组件又可以进行细分
1.2 Vue组件化思想
  • 组件化是Vue.js中的重要思想
    • 它提供了一种抽象,让我们可以开发出一个个独立可复用的小组件来构造我们的应用。
    • 任何的应用都会被抽象成一颗组件树
      Vue.js框架笔记_第9张图片
  • 组件化思想的应用:
    • 有了组件化的思想,我们在之后的开发中就要充分的利用它
    • 尽可能的将页面拆分成一个个小的、可复用的组件
    • 这样让我们的代码更加方便组织和管理,并且扩展性也更强

2. 组件化基础

1. 注册组件
1.1 注册的基本步骤
  • 组件的使用分成三个步骤:
    • 创建组件构造器
    • 注册组件
    • 使用组件
  • 我们来看看通过代码如何注册组件
  • 查看运行结果:
    • 和直接使用一个div看起来并没有什么区别。
    • 但是我们可以设想,如果很多地方都要显示这样的信息,我们是不是就可以直接使用来完成

Vue.js框架笔记_第10张图片

<div id="app">
  
  <my-cpn>my-cpn>
div>
<script>
// 1.创建组件构造器对象(步骤一)
const myComponent = Vue.extend({
  template: `
    

组件标题

我是组件中的一个段落内容

`
}) // 2.注册组件,并且定义组件标签的名称(步骤二) Vue.component('my-cpn', myComponent) const app = new Vue({ el: '#app' })
script>
1.2 注册组件步骤解析
  • Vue.extend()
    • 调用Vue.extend()创建的是一个组件构造器
    • 通常在创建组件构造器时,传入template代表我们自定义组件的模板
    • 该模板就是在使用到组件的地方,要显示的HTML代码
    • 事实上,这种写法在Vue2.x的文档中几乎已经看不到了,它会直接使用下语法糖,但是在很多资料还是会提到这种方式,而且这种方式是学习后面方式的基础
  • Vue.component()
    • 调用Vue.component()是将刚才的组件构造器注册为一个组件,并且给它起一个组件的标签名称
    • 所以需要传递两个参数
      • 注册组件的标签名
      • 组件构造器
  • 组件必须挂载在某个Vue实例下,否则它不会生效
2. 全局和局部组件
  • 当我们通过调用Vue.component()注册组件时,组件的注册是全局
    • 这意味着该组件可以在任意Vue示例下使用
  • 如果我们注册的组件是挂载在某个实例中, 那么就是一个局部组件
  • 全局组件
<div id="app">
  <my-cpn>my-cpn>
div>
<div id="app2">
  
  <my-cpn>my-cpn>
div>
<script>
	const cpnC = Vue.extend({
		template: `
			

组件标题

组件内容

`
}) Vue.component('my-cpn',cpnC) const app = new Vue({ el: '#app' })
script>
  • 局部组件
<div id="app">
  <my-cpn>my-cpn>
div>
<script>
	const cpnC = Vue.extend({
		template: `
			

组件标题

组件内容

`
}) const app = new Vue({ el: '#app', components: { my-cpn: cpnC } })
script>
3. 父组件和子组件
  • 在前面我们看到了组件树:
    • 组件和组件之间存在层级关系
    • 而其中一种非常重要的关系就是父子组件的关系
  • 我们来看通过代码如何组成的这种层级关系:
<div id="app">
  <cpn2>cpn2>
  
div>

<script src="../vue.js">script>
<script>
  // 1.创建第一个组件构造器(子组件)
  const cpnC1 = Vue.extend({
    template: `
      

我是子组件

`
}) // 2.创建第二个组件构造器(父组件) const cpnC2 = Vue.extend({ template: `

我是父组件

`
, components: { cpn1: cpnC1 } }) // root组件 const app = new Vue({ el: '#app', components: { cpn2: cpnC2 } })
script>
  • 父子组件错误用法:以子标签的形式在Vue实例中使用
    • 因为当子组件注册到父组件的components时,Vue会编译好父组件的模块
    • 该模板的内容已经决定了父组件将要渲染的HTML(相当于父组件中已经有了子组件中的内容了)
    • 是只能在父组件中被识别的
    • 类似这种用法,是会被浏览器忽略的
4. 注册组件语法糖
  • 在上面注册组件的方式,可能会有些繁琐
    • Vue为了简化这个过程,提供了注册的语法糖
    • 主要是省去了调用Vue.extend()的步骤,而是可以直接使用一个对象来代替
  • 语法糖注册全局组件局部组件
  • 全局组件
// 2.注册组件
Vue.component('cpn1', {
  template: `
    

我是标题1

我是内容, 哈哈哈哈

`
})
  • 局部组件
// 2.注册局部组件的语法糖
const app = new Vue({
  el: '#app',
  components: {
    'cpn2': {
      template: `
        

我是标题2

我是内容, 呵呵呵

`
} } })
5. 模板的分离写法
  • 我们通过语法糖简化了Vue组件的注册过程,另外还有一个地方的写法比较麻烦,就是template模块写法
  • 如果我们能将其中的HTML分离出来写,然后挂载到对应的组件上,必然结构会变得非常清晰
  • Vue提供了两种方案来定义HTML模块内容:
    • 使用

你可能感兴趣的:(#,前端进阶)