vue1-5

135 阅读10分钟

vue

MVC 和 MVVM 的区别

  • MVC: 针对后端的分层方式

    • model 数据连接层

    • view 视图层 .html .jsp ...

    • controller 控制层

      • router 路由分发
      • service 业务逻辑处理
    • ps: mvc 的数据流式单向

  • MVVM: 针对前端的分层方式,可以理解为在 MVC,V 层的基础上进一步划分 3 层

    • model 数据模型(后端网络请求得到的数据或者是自己写的死数据)
    • view 视图层 指定 model 的渲染区域
    • view model 管理 model 和 view 对数据的 存、取操作
  • MVP

vue 的模板语法

  • 渲染数据

{{msg}}

  • 数字计算

{{1+1}}

  • 解析函数

{{getData()}}

  • 三元运算
{{flag?'显示''隐藏''}}

指令

渲染数据

  • 插值表达式

    {{}}

  • v-html

  • v-text

  • v-pre

v-html、v-text、插值表达式有什么区别

  • 插值表达式 和 v-text 都是原样输出数据
  • v-html 先解析 html 元素再进行渲染

如何解决插值表达式的页面闪烁问题

  • 方式 1: 使用 v-text 代替 插值表达式
  • 方式 2: 使用 v-cloak 配置显示隐藏的样式

属性绑定

基本使用

  • string

    v-bind:属性名称 = "属性值" 简写 :属性名称 = "属性值"

  • object

    v-bind:属性名称 = "obj.属性值"

    v-bind="obj"

class 样式绑定

  • 普通数组

    :class="['class1','class2','class3']"

  • 数组三元

    :class="['class1','class2',flag?'class3':'']"

  • 数组对象 :class="['class1','class2',{class3:flag}]"

  • 普通对象 :class="{class1:true,class2:true,class3:true}" :class="objStyle"

style 样式绑定

  • object

    :style="obj"

  • array

    :style="[obj1,obj2]"

v-model 双向数据绑定

  • 数据流

    • 单向数据绑定: model 改变,view 跟着改变,不能反过来
    • 双向数据绑定: model 改变,view 跟着改变,反之亦然
  • 小结

    v-model 是 vue 中唯一一个可以使用双向数据绑定的指令,可以使用在表单和组件

    v-model 的原理

    1. 使用 v-bind 绑定数据
    2. 使用 v-on 绑定监听的函数如果数据发生改变重新赋值最新的数据

使用 js 模拟 vue 的双向数据绑定

事件绑定

v-on:事件类型="事件处理函数" 简写 @事件类型="事件处理函数"

修饰符

  • 事件修饰符

    stop 阻止冒泡 prevent 阻止默认行为 once 只阻止一次,跟随其他修饰符一起使用

  • 按键修饰符

    enter

列表渲染

基本使用

v-for="(item,index) in 数据"

  • arr

  • arrObj

  • obj

    <div v-for="(value,key,index) in obj"></div>
    
  • 数字

    <div v-for="(count,index) in obj"></div>
    <!-- count 的数值从 1 开始到指定的数据 -->
    

v-for 为什么跟随 key 一起使用

key 可以是唯一的 string/number key 建议不要使用 index 配置,因为 index 在使用 unshift 的时候不断的修改

  • 给指定的标签添加唯一的标识,防止页面在重新绘制的时候发生错乱
  • 确保 model 的值和 view 的值保持一致

... Diff 算法

条件渲染

v-if/v-else-if/v-else/v-show

v-if 和 v-show 的区别

  • v-if: 通过 js 操作 DOM 元素的添加和删除
  • v-show: 通过 css 控制元素的显示和隐藏

使用场景

  • v-if: 逻辑判断或者是少量的 DOM 操作
  • v-show: 用于频繁的点击操作

vue 的生命周期

  • 创建

    beforeCreate

    created

    最快在这里发起网络请求

  • 挂载

    beforeMounte

    mounted

    最快在这里操作 DOM 元素

  • 更新

    beforeUpdate

    updated

  • 销毁

    beforeDestroy

    卸载定时器

    destroyed

json-server 模拟接口

基本使用

  • 安装 json-server

    npm i json-server -g

  • 配置数据

    data.json

  • 运行命令生成接口

    json-server --watch --port 8888 --host 10.41.12.152 ./data.json

    --watch 实时监听文件的变化

    --port 设置端口号 默认为 3000

    --host 设置 ip 默认为 locahost

常用接口

get

post

  • 添加资源

http://localhost:3000/users

put 更新所有资源,会覆盖 patch 更新指定资源

delete

vue 中发起网络请求

vue-resource

基于 vue 开发的网络请求,2.0 之后不更新了

axios

任意的框架都可以使用,也不需要依赖于任意框架

www.npmjs.com/package/axi…

常用语法

  • get
// 字符串写法
axios
  .get("/user?ID=12345")
  .then(function (response) {
    // handle success
    console.log(response);
  })
  .catch(function (error) {
    // handle error
    console.log(error);
  })
  .then(function () {
    // always executed
  });
​
// 对象写法
axios
  .get("/user", {
    params: {
      ID: 12345,
    },
  })
  .then(function (response) {
    console.log(response);
  })
  .catch(function (error) {
    console.log(error);
  })
  .then(function () {
    // always executed
  });
// es7 写法
async function getUser() {
  try {
    const response = await axios.get("/user?ID=12345");
    console.log(response);
  } catch (error) {
    console.error(error);
  }
}
  • post
axios
  .post("/user", {
    firstName: "Fred",
    lastName: "Flintstone",
  })
  .then(function (response) {
    console.log(response);
  })
  .catch(function (error) {
    console.log(error);
  });
  • api 写法
// Send a POST request
axios({
  method: "post",
  url: "/user/12345",
  data: {
    firstName: "Fred",
    lastName: "Flintstone",
  },
});

配置根路径

// 方式1
axios.defaults.baseURL = "https://api.example.com";
axios.defaults.headers.common["Authorization"] = AUTH_TOKEN;
axios.defaults.headers.post["Content-Type"] =
  "application/x-www-form-urlencoded";
​
// 方式2
const instance = axios.create({
  baseURL: "https://api.example.com",
});

过滤器

  • 基本使用

Vue.filter('过滤器名称',callback)

  • 使用场景

    • 插值表达式 {{msg|过滤器名称}}
    • 属性绑定 :msg="msg|过滤器名称"
  • ps: 当全局过滤器和局部过滤器同时存在的时候,就近原则使用局部的过滤器

    局部过滤器只能使用在当前的实例,全局过滤器可以使用在任意的实例

自定义指令

Vue.directive("指令名称", {
  // el 添加该指令的元素的DOM
  // binding 是一个对象可以通过 binding.value 获取指令的值
  bind(el, binding) {},
  inserted() {},
  updated() {},
});
​
// 自动执行了 bind 和 updated
Vue.directive("指令名称", callback);

动画

  • 进入

    v-enter 起点

    v-enter-to 目的点

    v-enter-active 进入的时间

  • 离开

    v-leave 目的点

    v-leave-to 终点

    v-leave-active 离开的时间

原生动画的基本使用

  1. 可切换的元素

  2. 使用 transition 包裹动画元素

  3. 设置动画的样式

    • 设置起点和终端的状态和位置
    • 设置进入和离开的时间

第三方动画 animate.css

  • enter-active-class 设置进入的动画

  • leave-active-class 设置离开的动画

  • duration 设置动画的时间,时间不要超过 1000

    • number/string 统一配置进入和离开的时间 :duration="800" duration="800"
    • object :duration="{enter:500,leave:300}"

列表动画

transition-group

半场动画

beforeEnter

enter

afterEnter

组件

什么是组件化

当我们遇到复杂问题时,很难一次性搞定所有问题,所以这时需要把问题拆解,把小问题都解决后综合起来就能得到这个问题的解决方案,听起来很熟悉吧!其实在动态规划中就是这种思想了,只不过是最优解和解决方案的区分。

组件化也是这种解决问题的思路,当一个项目中的功能逻辑特别复杂时,我们很难一次性完成所有逻辑交互,因为容易发生冗余或回调地狱,一旦某一部分出错,很难追究到哪行代码出现问题。同时一个人的精力是有限的,为了减轻个人的压力,将问题分为小的功能模块,既可以减少管理和维护该界面的成本,也可以适合团队合作。

但其实 Vue 的前端开发不需要很多人,因为它是轻量级的,所以实际项目中只需要美工人员把设计好的原型发给一两个前端开发人员就行了,至于为什么需要这么少的开发人员,很大程度上因为 Vue 的组件化开发让业务逻辑更清晰。

ps: 组件化: 是针对前端 ui 的一种划分方式 ,把前端的业务分层多个组件单独管理 模块化: 一个 js 文件就是一个模块,在一个 js 文件中引入另一个 js 文件

vue 组件化思想

  • 组件化的思想让我们能够开发出一个个独立且可复用的小组件来构造我们的应用。
  • 每一个应用(功能)都可以抽象成一个组件树。

组件

  • 尽可能的将页面拆分成小且可复用的组件。这样让我们的代码更加方便组织和管理,并且扩展性也更强。

vue 组件化的好处

  1. 组件是独立和可复用的代码组织单元。组件系统是 vue 核心特性之一,它使开发者使用小型、独立和通常可复用的组件构建大型应用;
  2. 组件化开发能大幅度提高应用开发效率、测试性、复用性等;
  3. 能让 web 前端代码实现“高内聚 低耦合”,使得前端开发的过程变成搭积木的过程。

组件的基本使用

  1. 定义组件
const Login = {
  template: ``,
};
​
const Login = Vue.extend({
  template: ``,
});
  1. 注册组件
// 全局注册
Vue.component("组件名称", 组件的返回值);
​
// 局部注册
new Vue({
  components: {
    组件名称: 组件的返回值,
  },
});
  1. 渲染组件

    • 以组件名称作为标签直接渲染
    • 以 component 渲染,通过 is 属性设置具体渲染那个组件,一般用于组件的切换

组件中的 data 为什么是一个 function

动态组件和异步组件

组件通信(9 种方式)

每个组件的数据都是独立的,组件之间通信需要按照一定的方式传递数据

父传子

  1. 在渲染的子组件上使用 v-bind 的方式传递父组件的数据
  2. 在子组件中使用 props 接受传递的数据
  • ps:

    • props 的对象写法可以约束传递的数据的类型
    • props 的对象写法可以设置属性的默认值
    • props 是只读的不能被修改

子传父

  1. 在渲染的子组件上使用 v-on 的方式监听父组件的函数
  2. 在子组件中使用$emit 的方式调用函数,调用的同时传递子组件的数据

兄弟组件传值(事件总线)

b --> a

  1. 创建一个空的 vue 实例 (eventBus)
  2. 在组件 a 中使用 $on 的方式监听函数
  3. 在组件 b 中使用 $emit 调用函数,调用的同时传递数据

爷孙传值 attrsattrs、listeners

跨多组件传值 provide、inject

refsrefs、parent、$root

组件插槽

可以在父组件中直接修改子组件的 ui

匿名插槽

具名插槽

作用域插槽

插槽的优点

  • 可以在父组件中定制子组件的 ui
  • 可以解决多层组件传参问题
  • 可以对组件进行抽离方便管理

路由

路由是一种对应关系

什么是后端路由

客户端请求的 url 地址和服务端对该地址的处理函数的对应关系

什么是前端路由

路由是根据不同的 url 地址展示不同的内容或页面

前端路由就是把不同路由对应不同的内容或页面的任务交给前端来做,之前是通过服务端根据 url 的不同返回不同的页面实现的

hash

history

什么时候使用前端路由

在单页面应用,大部分页面结构不变,只改变部分内容的时候使用

前端路由有什么优缺点

  • 优点:

    用户体验好,不需要每次都从服务器全部获取,快速展现给用户

  • 缺点:

    • 不利于 SEO
    • 使用浏览器的前进,后退键的时候会重新发送请求,没有合理利用缓存
    • 单页面无法记住之前滚动的位置,无法在前进,后退的时候记住滚动的位置

vue 中路由基本使用

  1. 通过 script 标签引入 vue-router

  2. 定义组件

  3. 实例化路由对象 new VueRouter

  4. 配置路由的规则

    #/home ---> 组件

  5. 挂载路由

    设置路由和 vue 的关系

  6. 渲染路由

    router-view

    router-link

路由高亮

  • router-link-active
  • linkActiveClass: 'active'

路由重定向、404

  • redirect
 {
    path: '/',
    redirect: '/home'
  }'
  • 404
  {
    path: '*',
    component: NotFoundPage
  }'

路由传参

  • query

    #/home?name=fly&age=18

  • params

    #/home/fly/18

     {
        path: '/home/:name/:age',
        component: Home
      }'
    

路由编程式导航

this.$router.push()

嵌套路由

  {
    path: '/home',
    component: Home,
    children: [
      {
        path: '/home/recomment',
        component: Recomment
      }
    ]
  }

命名视图路由

{ path: '/', components: { default: Header, main: Main, footer: Footer } }

<router-view></router-view>
<router-view name="main"></router-view>
<router-view name="footer"></router-view>

路由进阶

  • beforeEach

    全局路由前置守卫

    router.beforeEach((to, from, next) => {});
    
  • afterEach()

    全局路由后置守卫

  • 路由独享守卫

    beforeEnter()

  • 组件内置守卫

    beforeRouteEnter(to,from,next) {

    }

methods、watch、computed 有什么区别

  • methods:适合用于业务逻辑处理

    多次调用的时候不会缓存

  • watch:比较适合侦听单个数据,或者是路由

    可以侦听实例上的任意属性

  • computed:适合计算多个属性的结果

    可以缓存数据方便下次使用

watch 的两种用法

  • 浅层侦听
  • 深度侦听