Vue学习分享

介绍:Vue起初是一个构建数据驱动的web界面的库,通过简单的API提供高效的数据绑定和灵活的组件系统,但随着vue生态圈的发展,如vue-router,vue-resource等的推出,vue已经算得上是个轻量级的MVVM框架了,官方定义vue是一套用于构建用户界面的渐进式框架。相较于Angular和React框架,vue的的学习曲线更平稳,这点也是我选择Vue入门的原因。

如何安装?

  • 直接HTML引入 script

  • vue cli方式
$ npm install vue

Vue的核心思想

Vue学习分享_第1张图片
vue.jpg
  • 数据驱动

DOM是数据的一种自然映射,手动操作DOM是一件非常繁索且容易出错的事情,而使用vue.js后,就省去了手动操作DOM的步骤,在Vue.js里我们只需要操作数据,vue会通过Directives指令去修改对应的DOM,从而实现数据驱动。

  • 组件化

组件化的目的是扩展HTML元素,封装可重用代码

通过上图,我们可以粗略理解为一个简单的vue应用大概先分两部分:Vue实例、 HTML

第一部分 : vue实例

每个 Vue 应用都是通过创建一个新的 Vue 实例开始,语法如下:

var vm = new Vue({
  // 选项
})

构造器的常用参数属性包含:eldatamethodscomputedwatch生命周期钩子等,具体应用如下:

  • el:提供一个在页面上已存在的 DOM 元素作为 Vue 实例的挂载目标,在vue单文件情况下不需要该属性
#挂载到id为app的DOM节点上
el: '#app'
  • data: 用于定义数据属性,当 Vue 实例被创建时,它向 Vue 的响应式系统加入了 data 对象中所有的属性。当这些属性的值变化时,HTML 视图将也会产生相应的变化。
# 实例创建之后,可通过 vm.$data 访问原始数据对象。Vue 实例也代理了 data 对象上所有的属性,因此访问 vm.a 等价于访问 vm.$data.a。
data: {
  newTodoText: '',
  visitCount: 0,
  hideCompletedTodos: false,
  todos: [],
  error: null
}
  • methods:用于定义的函数,通过 return 来返回函数值。
// 在组件中
methods: {
  reversedMessage: function () {
    return this.message.split('').reverse().join('')
  }
}
  • computed 用于计算属性,当模板中的逻辑复杂时,代码非常难以看懂理解,可考虑把逻辑写在computed中,我们用 methods 替代 computed,效果一样,但 computed 基于它的依赖缓存,只有相关依赖发生改变时才会重新取值。而使用 methods ,在重新渲染的时候,函数总会重新调用执行。可以说 computed 性能会更好,除非你不希望缓存。
computed: {
    // 计算属性的 getter
    reversedMessage: function () {
      // `this` 指向 vue 实例
      return this.message.split('').reverse().join('')
    }
  }
  • watch 监听属性来响应数据的变化,当我们再输入框输入数据时,watch 会实时监听数据变化并改变自身的值。
var vm = new Vue({
  el: '#demo',
  data: {
    firstName: 'Foo',
    lastName: 'Bar',
    fullName: 'Foo Bar'
  },
  watch: {
    firstName: function (val) {
      this.fullName = val + ' ' + this.lastName
    },
    lastName: function (val) {
      this.fullName = this.firstName + ' ' + val
    }
  }
})
  • vue实例还有一系列的生命周期钩子,给了用户在不同阶段添加自己的代码的机会。
    • beforeCreate 在实例初始化之后调用
    • created 在实例创建完成后被立即调用
    • beforemount 在挂载开始之前被调用
    • mounted 实例被挂载后调用
    • beforeupdate 数据更新时调用
    • updated 由于数据更改导致的虚拟 DOM 重新渲染和打补丁,在这之后会调用该钩子
    • beforeDesgroy 实例销毁之前调用
    • destroyed 实例销毁后调用
new Vue({
  data: {
    a: 1
  },
  created: function () {
    // `this` 指向 vue 实例
    console.log('a is: ' + this.a)
  },
  beforeCreate: function () {
    console.log('beforeCreate')
  }
})

备注:

  • 不要在选项属性或回调上使用箭头函数,比如 created: () => console.log(this.a),因为箭头函数并没有 this
  • 当这些数据改变时,视图会进行重渲染。但只有当实例被创建时就已经存在于 data 中的属性才是响应式的;
  • Vue实例针对数据、DOM、资源、组合等都有非常多灵活的属性,具体可查看官方API

第二部分 : HTML

vue实例承载了数据和逻辑相关的内容,那么HTML就是处理我们view相关内容了,Vue.js 使用了基于 HTML 的模板语法,允许开发者声明式地将 DOM 绑定至底层 Vue 实例的数据。

插值表达式

数据绑定最常见的形式就是使用“Mustache”语法 (双大括号)

# 基本形式 ,无论何时,绑定的数据对象上 value 属性发生了改变,插值处的内容都会更新
{{ value }}
# 只需渲染一次数据
{{ *value }}
#可放在HTML标签内
  • # 表达式 {{ number / 100 }} {{ true ? 1 : 0 }} {{ example.split(",") }} # !!错误示例(语句并非表达式,条件控件语句也是不支持的) {{var logo = 'DDEF'}} {{if (true) return 'DDEF'}} # 过滤器: {{ date | formateDate }} {{ example | toUpperCase}}
    指令

    指令 (Directives) 是带有 v- 前缀的特殊 attribute。指令的职责是当表达式的值改变时,将其产生的连带影响,响应式地作用于 DOM。包含v-textv-htmlv-showv-ifv-elsev-else-ifv-forv-onv-bindv-modelv-slotv-prev-cloakv-once,在实际开发中应用非常频繁,下面我们来详细聊聊它们的用法。
    v-bind : 动态地绑定一个或多个特性,或一个组件 prop 到表达式。

    
    
    
    
    
    
    
    
    
    8891汽车

    v-show 根据表达式之真假值,切换元素的 display CSS 属性

    
    
    

    Hello!

    v-if 条件判断,根据表达式的值在DOM中生成或移除一个元素

    
    

    现在你看到我了

    Now you see me
    Now you don't
    A
    B
    C
    Not A/B/C

    v-for 循环语句 :

    
    
    • {{ item.message }}
    • {{ parentMessage }} - {{ index }} - {{ item.message }}
    • {{ value }}
    {{ name }}: {{ value }}
    {{ index }}. {{ name }}: {{ value }}
    {{ item.message }}
    {{ n }}
    #VUE实例部分
    var example1 = new Vue({
      el: '#example-1',
      data: {
        items: [
          { message: 'Foo' },
          { message: 'Bar' }
        ],
        object: {
          title: 'How to do lists in Vue',
          author: 'Jane Doe',
          publishedAt: '2016-04-10'
        }
      }
    })
    

    备注:当数组出现变动时,Vue是如何检测呢?Vue 将被侦听的数组的变异方法进行了封装,它们能触发实图更新。所以建议尽量避免直接设置数据绑定的数组元素,因为这些变化不会被vue.js检测到,这些被封装过的方法包括:

    • push()
    • pop()
    • shift()
    • unshift()
    • splice()
    • sort()
    • reverse()

    相比之下,也有非变异 (non-mutating method) 方法,它们不会改变原始数组,而总是返回一个新数组。

    • filter()
    • concat()
    • slice()

    v-on : 用于监听 DOM 事件,并在触发时运行一些 JavaScript 代码

    
    

    Vue.js 为 v-on 提供了事件修饰符。之前提过,修饰符是由点开头的指令后缀来表示的。

    • .stop
    • .prevent
    • .capture
    • .self
    • .once
    • .passive

    为了在必要的情况下支持旧浏览器,Vue 提供了绝大多数常用的按键码的别名:

    • .enter
    • .tab
    • .delete (捕获“删除”和“退格”键)
    • .esc
    • .space
    • .up
    • .down
    • .left
    • .right

    v-model : 用来在 input、select、textarea、checkbox、radio 等表单控件元素上创建双向数据绑定,根据表单上的值,自动更新绑定的元素的值。

    
    
    
    
    
    
    

    v-slot: 插槽,主要用于内容分发,插槽内可以包含任何模板代码,包括 HTML、其它组件等

    
      Your Profile
    
    
    
    
      
      
    
    
    
    
      
       
      
      
      Your Profile
    
    
    

    v-text: 用于更新元素的 textContent

    
    
    {{msg}}
    

    v-html : 用于更新元素的 innerHTML

    
    

    v-pre: 用于跳过这个元素和它的子元素的编译过程。可以用来显示原始 Mustache 标签

    
    {{ this will not be compiled }}
    

    v-once : 只渲染元素和组件一次。

    这个将不会改变: {{ msg }}
    

    指令会在写HTML时大量应用到,特别是表单处理等,建议多加练习。

    组件

    组件化的目的是扩展HTML元素,封装可重用代码;组件其实是可复用的 Vue 实例

    基础用法 ,组件注册 - 全局注册:

    // 定义名为 todo-item 的新组件
    Vue.component('todo-item', {
      template: '
  • 这是组件内容
  • ', }) var app = new Vue(...)

    组件注册 - 局部注册:

    var ComponentA = {
      template:'
    局部注册组件的内容
    ' } new Vue({ el: '#app', components: { 'component-a': ComponentA, } })
    #局部注册的组件在其子组件中不可用。例如,如果你希望 ComponentA 在 ComponentB 中可用,则你需要这样写:
    var ComponentA = { /* ... */ }
    
    var ComponentB = {
      components: {
        'component-a': ComponentA
      },
      // ...
    }
    

    在模块系统中局部注册

    #这样 ComponentA 和 ComponentC 都可以在 ComponentB 的模板中使用了
    import ComponentA from './ComponentA'
    import ComponentC from './ComponentC'
    
    export default {
      components: {
        ComponentA,
        ComponentC
      },
      // ...
    }
    
    组件-数据传递:

    props:props 可以是数组或对象,用于接收来自父组件的数据。

    • 数组模式
    props: ['title', 'likes', 'isPublished', 'commentIds', 'author']
    
    • 对象模式
    //若想每个prop 都指定的值类型。可以用对象形式列出prop,属性的名称和值分别是prop 各自的名称和类型
    props: {
      title: String,
      likes: Number,
      isPublished: Boolean,
      commentIds: Array,
      author: Object,
      callback: Function,
      contactsPromise: Promise // or any other constructor
    }
    
    • Prop 验证 ,我们可为组件的 prop 指定验证要求,例如你知道的这些类型。如果有一个需求没有被满足,则 Vue 会在浏览器控制台中警告你。
    Vue.component('my-component', {
      props: {
        // 基础的类型检查 (`null` 和 `undefined` 会通过任何类型验证)
        propA: Number,
        // 多个可能的类型
        propB: [String, Number],
        // 必填的字符串
        propC: {
          type: String,
          required: true
        },
        // 带有默认值的数字
        propD: {
          type: Number,
          default: 100
        },
        // 带有默认值的对象
        propE: {
          type: Object,
          // 对象或数组默认值必须从一个工厂函数获取
          default: function () {
            return { message: 'hello' }
          }
        },
        // 自定义验证函数
        propF: {
          validator: function (value) {
            // 这个值必须匹配下列字符串中的一个
            return ['success', 'warning', 'danger'].indexOf(value) !== -1
          }
        }
      }
    })
    

    类型检查 : type 可以是下列原生构造函数中的一个:

    • String
    • Number
    • Boolean
    • Array
    • Object
    • Date
    • Function
    • Symbol

    给 prop 传入数据 - 示例:

    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    

    组件中,data必需是函数,因为它是引用类型,如果继续使用对象,则会在组件复用时相互影响:

    # 一个组件的 data 选项必须是一个函数,因此每个实例可以维护一份被返回对象的独立的拷贝
    data: function () {
      return {
        count: 0
      }
    }
    
    组件通信
    • 父传子props

    所有的 prop 都使得其父子 prop 之间形成了一个单向下行绑定:父级 prop 的更新会向下流动到子组件中,但是反过来则不行。这样会防止从子组件意外改变父级组件的状态,从而导致你的应用的数据流向难以理解。

    • 子传父$emit,可以使用 $emit 触发父组件的自定义事件
    // 父组件
    Vue.component('parent', {
      template:`
        
    `, data() { return { message: 'hello' } }, methods:{ // 执行子组件触发的事件 getChildData(val) { console.log(val); } } }); // 子组件 Vue.component('child', { template:`
    `, props:['message'], data() { return { // 这里是必要的,因为你不能直接修改 props 的值 myMessage: this.message } }, methods:{ passData(val) { // 数据状态变化时触发父组件中的事件 this.$emit('getChildData', val); } } }); var app=new Vue({ el: '#app', template: `
    ` });
    • 非父子组件 : vuex,这部分暂时还没深入学习,以后再展开详解。

    单文件组成

    使用 Vue.componen 来定义全局组件,然后用 new Vue({ el: '#container '}) 在每个页面内指定一个容器元素,在复杂的项目中会以下明显缺点:

    • 全局定义 (Global definitions) : 强制要求每个 component 中的命名不得重复
    • 字符串模板 (String templates) : 缺乏语法高亮,在 HTML 有多行的时候,需要用到丑陋的 \
    • 不支持 CSS (No CSS support) : 当 HTML 和 JavaScript 组件化时,CSS 明显被遗漏
    • 没有构建步骤 (No build step) : 只能用 HTML 和 ES5 JavaScript,而不能使用预处理器,如Babel

    针对以上缺点,vue提供了文件扩展名为 .vue 的 single-file components(单文件组件) 为以上所有问题提供了解决方法,并且可以用 webpack 等构建工具,好在vue提供了脚手架工具Vue CLI 官方地址

    安装Vue CLI

    npm install -g @vue/cli
    # OR
    yarn global add @vue/cli
    # 检查其版本是否正确
    vue --version
    

    现在就可以通过Vue CLI创建工程,然后根据我们的需求配置并生成项目

    vue create demo
    
    # vue create 命令有一些可选项,具体可查看
    vue create --help
    # 也能通过 vue ui 命令以图形化界面创建和管理项目
    vue ui
    

    .vue文件结构如下:

    
    
    
    

    现在我们获得:

    • 完整语法高亮
    • CommonJS 模块
    • 组件作用域的 CSS

    至此,VUE的一些基本用法都已经有大概的了解,后面还有更多知识要学习,比如前面工程化vue第三方库等等。

    vue生态之vue-router

    Vue.js路由,允许我们通过不同的 URL 访问不同的内容,从而实现多视图的单页Web应用
    CDN方式

    https://unpkg.com/vue-router/dist/vue-router.js
    

    NPM方式安装

    cnpm install vue-router
    

    vue-router应用示例: 是一个组件,该组件用于设置一个导航链接,切换不同 HTML 内容。
    to 属性为目标地址, 即要显示的内容。

    
    
     
    

    Go to Foo Go to Bar

    JS部分

    // 0. 如果使用模块化机制编程,导入 Vue 和 VueRouter,要调用 Vue.use(VueRouter)
     
    // 1. 定义(路由)组件。
    // 可以从其他文件 import 进来
    const Foo = { template: '
    foo
    ' } const Bar = { template: '
    bar
    ' } // 2. 定义路由 // 每个路由应该映射一个组件。 其中"component" 可以是通过 Vue.extend() 创建的组件构造器,或者,只是一个组件配置对象。 const routes = [ { path: '/foo', component: Foo }, { path: '/bar', component: Bar } ] // 3. 创建 router 实例,然后传 `routes` 配置 const router = new VueRouter({ routes // (缩写)相当于 routes: routes }) // 4. 创建和挂载根实例。记得要通过 router 配置参数注入路由,从而让整个应用都有路由功能 const app = new Vue({ router }).$mount('#app')

    相关属性

    to : 目标路由的链接。 当被点击后,内部会立刻把 to 的值传到 router.push(),所以这个值可以是一个字符串或者是描述目标位置的对象。

    
    Home
    
    Home
    
    
    Home
    Home
    Home
    
    
    User
    
    
    Register
    

    replace :设置 replace 属性后,点击时会调用 router.replace() 而不是 router.push(),导航后不会留下 history 记录。

    
    

    append :设置 append 属性后,则在当前 (相对) 路径前添加基路径。例如,我们从 /a 导航到一个相对路径 b,如果没有配置 append,则路径为 /b,如果配了,则为 /a/b

    
    

    tag : 有时候想要 渲染成某种标签,例如

  • 。 于是我们使用 tag prop 类指定何种标签,同样它还是会监听点击,触发导航

    foo
    
    
  • foo
  • active-class :链接激活时使用的 CSS 类名。可以通过以下代码来替代。
    exact-active-class : 链接被精确匹配的时候应该激活的 class

    Router Link 1
    Router Link 1
    

    event : 声明可以用来触发导航的事件

    Router Link 1
    
  • 你可能感兴趣的:(Vue学习分享)