Vue 总结

前言

前些天刚完成了全栈的实践,基本上一个完成了主要的页面内容.
如果熟悉Vue对自己的技术栈有一定的提升,也提升了开发效率.

Vue是基于MVVM的思想进行设计.
其实Vue也没啥难得,MVVM的理论早就开始盛行了,只是Vue的设计比较巧妙,赢得了开发者的喜爱.
通过一篇文章想对Vue的理解提升到一定的层次是不实际的,看是看不会的,计算机本来就是实践性很强的课程,希望大家最好去实战一下完成一个小项目,去提升自己的能力.

基础环境

构建工具是用的webpack,js语法支持es2015,样式处理是采用的less.

实例

如何创建一个Vue实例

let vm = new Vue();

数据绑定

我们有了这个实例可以去进行哪些操作,如何进行数据传递.

let obj = {test:'data'};
let vm = new Vue({
    data:obj
});

vm.data == obj //true

上述的例子中vm的data属性引用了obj,obj.test的值改变会影响到vm.test的值.

vm.a = 'test' 

动态新增属性,虽然vm有了新的属性但是这样不是响应式的,也就不会对视图进行影响,因此如果需要响应式的数据,我们可以在data提前声明一个默认值

实例属性与方法都与$符号开头.

模板

指令

Vue当中以v-开头的都是指令,一般为 JavaScript 表达式

<select v-bind:selected="true"></select>

v-bind指令用于将元素的属性与表达式进行绑定,可以简写为:.
v-on指令用于将元素
v-bind 可以简写为:
v-on 可以简写为@

<div @click='clickDiv'> </div>

输出文本

我们如何输出data中的一个JS变量,

<div>{{message}}</div>

我们可以用v-once指令 ,限制渲染次数,渲染一次后不在渲染,与数据解绑.

<div v-once >{{test}}</div>

test数据发生改变后不会影响div里的内容展示

绑定html属性

如何将select 下拉框的disabled属性和我们的数据进行关联呢

<select :disabled="isDisabled"></select>

isDisabled 的值是 null、undefined 或 false,则 disabled 特性甚至不会被包含在渲染出来的 select元素中。

JavaScript表达式

模板不仅可以输出变量,也可以使用JavaScript**表达式**

<div id=" 'list' + id ">
{{test.reverse()}}
</div>

上述例子使用了两次js表达式
id属性的字符串的拼接,模板输出

计算属性和侦听器

计算属性

当我们要对属性进行复杂的逻辑处理时,就不能简单的在模板当中使用JS表达式.要将属性写成计算属性.

定义
new Vue({
    computed:{
        reverseError(){
            return this.error.reverse();
        }
    }
})

上述例子我们定义了一个error的计算属性.这个属性实质是一个getter函数,声明在了computed当中.

缓存机制

计算属性是基于他们的依赖(响应式的依赖)进行缓存.
一个computed可以依赖于另一个computed

Setter

默认的定义方式我们只可以定义getter函数,除此之外我们也可以定义setter函数


computed:{
    myProcess:{
        get: function () {
        //todo
        },
        set: function (newValue) {
        //todo
        }
    }
}

侦听属性

当我们需要监控一个对象的变化时,我们需要使用到这个方法.

例如:

watch:{
    $route(to, from){
        console.log(to);
        console.log(from)
    }
}

当route的path发生变化的时候,这样我们可以route输出新旧值.

样式处理

样式处理的方式比较灵活也很强大,与jQuery操作完全不一致,所以这个理解起来有些复杂.
类与内联样式用法一致,只不过在绑定时一个绑定style一个绑定class.

对象语法

<div :class="{active:isActive,'error':isError}"></div>

上述例子将active 展示类与属性isActive属性进行了绑定.当isActive变为false时,那么active class将不会进行显示.

样式对象绑定

非内联可以减少耦合.

<div :class="classObj"></div>
data:{
    classObj:{
        isActive:true,
        'text-error':false
    }
}

计算属性

computed:{
    classObj(){
        return {
            isActive:true,
            'text-danger':this.error && this.error.type === 'fatal'
        }
    }
}

三元与数组

<div class="[isActive?active: 'abnormal', normal]"></div>

条件处理

分组渲染

<div v-if="isShow == A"></div>
<div v-else-if="isShow == B"></div>
<div v-else></div>

上述例子当中,如果符合对应的条件就渲染对应的div.
会触发子组件的销毁以及重建.

v-show

v-show 只是简单地切换元素的 CSS 属性 display,v-if是控制这个属性是否渲染在html中。

<div v-show="myShow"></div>

列表渲染

如何遍历数组

v-for可以将数组渲染成多个元素.

<ul>
<li v-for="item in listItem">{{item.info}}</li>
</ul>
<ul>
<li v-for="(item, index) in listItem">{{item.info}}</li>
</ul>

如何遍历对象

<ul>
<li v-for="value in obj">{{value}}</li>
</ul>
<ul>
<li v-for="(value, key,) in obj">{{value, key}}</li>
</ul>
<ul>
<li v-for="(value, key, index) in obj">{{value, key, index}}</li>
</ul>

当需要数组的索引时,可以指定index.

遍历时顺序

默认情况下,顺序发生改变时,Vue不会将当前渲染改变顺序.

如果需要顺序变化时,需要key进行绑定:

<div v-for="item in items" :key="item.id">
</div>

何时触发重新渲染

1.Vue 包含一组观察数组的变异方法,所以它们也将会触发视图更新

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

2.替换数组
当我们进行数组替换时,也会触发视图的重新渲染.

注意:
以下时机不会进行重新
1.当你利用索引直接设置一个项时,不会进行改变 TODO:Why
2.当你修改数组的长度时
3.动态添加属性需要使用Vue.set()方式进行添加,否则对象将不会是响应式的.

v-for与v-if

v-for比v-if拥有更高的优先级,每次执行v-for会调用v-if指令进行判断.

事件处理

v-on(@)可以监听DOM事件.

<div id="example-1">
  <button @:click="counter += 1">Add 1</button>
</div>

接收原生event对象

<div @click="clickButton"></div>

我们可以默认接收event对象

methods:{
    clickButton(event){
        //TODO  
    }
}

这样我们就可以在点击事件当中接收对应的事件了.

传入自定义的参数

当我们触发事件时,可能我们不仅需要event对象还需要额外的自定义的参数那么我们就可以 这样做:

<div @click="clickButton(info)"></div>
methods:{
    clickButton(info,event){
        //TODO  
    }
}

这样我们既可以接收自定义的参数,也可以接收event对象.

事件修饰符

当我们需要对事件进行处理时,需要对事件触发增加条件限制,我们就可以用到修饰符.
比如一个创建订单按钮 防止用户重复点击.我们可以将点击事件设置为触发一次.

<div @click.once=></div>

修饰符如下:

<!-- 阻止单击事件继续传播 -->
<a v-on:click.stop="doThis"></a>

<!-- 提交事件不再重载页面 -->
<form v-on:submit.prevent="onSubmit"></form>

<!-- 修饰符可以串联 -->
<a v-on:click.stop.prevent="doThat"></a>

<!-- 只有修饰符 -->
<form v-on:submit.prevent></form>

<!-- 添加事件监听器时使用事件捕获模式 -->
<!-- 即元素自身触发的事件先在此处处理,然后才交由内部元素进行处理 -->
<div v-on:click.capture="doThis">...</div>

<!-- 只当在 event.target 是当前元素自身时触发处理函数 -->
<!-- 即事件不是从内部元素触发的 -->
<div v-on:click.self="doThat">...</div>

表单输入绑定

v-model

我们可以使用v-model指令在表单inputtextarea进行数据的双向绑定.

注意:v-model 会忽略所有表单元素的 value、checked、selected 特性的初始值而总是将 Vue 实例的数据作为数据来源.

下拉框示例:

<div>
  <select v-model="selected">
    <option disabled value="">请选择</option>
    <option v-for="(item, index) in items" :value="idex">{{item}}</option>
  </select>
  <span>Selected: {{ selected }}</span>
</div>
data:{
    items:['A', 'B', 'C']
}

v-model的修饰符

在默认情况下,v-model 在每次 input 事件触发后将输入框的值与数据进行同步 (除了上述输入法组合文字时)。你可以添加 lazy 修饰符,从而转变为使用 change 事件进行同步.

<input v-model.lazy="msg" >

如果想自动将用户的输入值转为数值类型,可以给 v-model 添加 number 修饰符:

<input v-model.number="age" type="number">

trim修饰符,将用户输入的空格过滤.

<input v-model.trim="msg">

组件

组件就是封装可用的代码可以在多处进行调用.

使用组件

全局注册

全局注册顾名思义,全局注册执行后,所有的vue实例都可以用这个组件.

Vue.component('my-component', {
  // 选项
})
局部注册

局部注册后只有指定实例可以使用该组件.

var Child = {
  template: '<div>A custom component!</div>'
}

new Vue({
  // ...
  components: {
    // <my-component> 将只在父组件模板中可用
    'my-component': Child
  }
})

is的使用

is可以在一些元素当中防止解析产生问题.如table,ul,ol等当中允许包含限制元素.

<table>
<my-table-thead></my-table-thead>
</table>

上述例子当中元素的解析可能会产生问题.这时候我们可以使用is进行指定组件.

<table>
<thead is="my-table-thead"></thead>
</table>

将组件内data设置为函数

这样做的目的是为了防止一个模板当中渲染多个组件,data引用了一个相同的对象,这样往往会造成不想要的结果.

Vue.component('my-component', {
template: '<div>{{source}}</div>',
  data: function () {
    return {
        source:11
    }
  }
})

组件通信

Vue当中的父子组件通信的逻辑稍微复杂.
数据流是单向的,一般情况下,子组件不能直接修改父组件传递的数据

父组件向子组件传递数据

prop传递数据

组件实例的作用域是孤立的。这意味着不能 在子组件的模板内直接引用父组件的数据。父组件的数据需要通过 prop 才能下发到子组件中。

子组件:

Vue.component('child', {
  props: ['message'],
  template: '<span>{{ message }}</span>'
})

父组件:

<child :message="parentMsg!"></child>
new Vue({
  el: '#prop-example-2',
  data: {
    parentMsg: 'Message from parent'
  }
})

这样我们就可以将父组件的值传递于子组件,而且是动态更新的.

prop验证
Vue.component('example', {
  props: {
    // 基础类型检测 (`null` 指允许任何类型)
    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 value > 10
      }
    }
  }
})

type检测的类型:

String
Number
Boolean
Function
Object
Array
Symbol

子组件向父组件传递数据

再次强调,子组件不能直接修改父组件的数据.那么如何向父组件传递数据呢,需要采用事件的处理方式进行通信.

事件机制
$emit(eventName, optionalPayload);
$on(eventName)

optionalPayload 可以在触发时间时提供额外的参数.

<child @click='handleSendMessage'></child>
<div id="message-event-example" @message='hanleMessage'></div>
Vue.component('child', {
  props: ['message'],
    methods: {
    handleSendMessage: function () {
      this.$emit('message', { message: this.message })
    }
  }
})

new Vue({
  el: '#message-event-example',
  data: {
    messages: []
  },
  methods: {
    handleMessage: function (payload) {
      this.messages.push(payload.message)
    }
  }
})

双向数据绑定

sync修饰符

.sync修饰符可以使数据进行数据的双向绑定,只要子组件修改也会变更父组件的数据.

本质是对.sync进行了转换,将数据转换成事件机制进行同步.

因此在父组件当中

<child :message.sync="message"></child>

这样就可以在父子组件当中进行数据传递.

表单输入事件

v-model 进行双向数据绑定 本质上是进行了转换

<my-input v-model="price"></my-input>

转换后:

<my-inpu v-bind:value="price"  v-on:input="price = arguments[0]"></my-input>

组件内部需要显示的声明value在props

Vue.component('my-input', {
  props: ['value'],
})
自定义组件

下拉选框与复选框的value被用做了别的用途,因此我们可能不需要改变value的值.

Vue.component('my-checkbox', {
  model: {
    prop: 'checked',//组件内接受的属性
    event: 'change' //组件内改事件触发后,将父组件元素绑定的model进行转换
  },
  props: {
    checked: Boolean,
    value: String
  }
})
<my-checkbox v-model="foo" value="some value"></my-checkbox>

转换后


<my-checkbox
  :checked="foo"
  @change="val => { foo = val }"
  value="some value">
</my-checkbox>

插槽

单个插槽

子组件通过slot可以获取在父组件创建的子组件内部的内容.实质是进行内容的替换.

父组件

<child> <p>插入内容</p></child>

子组件

<template><div class="child"><slot></slot></div></template>

编译后:

<div class="child"><p>插入内容</p></div>
具名插槽

具名插槽就是告诉子组件插入到指定的插槽当中.

父组件

<child><h1 slot="header">插入标题</h1> <p slot="content">插入内容</p></child>

子组件

<template><div class="child"><slot name="header"></slot><slot  name="content"></slot></div></template>

编译后:

<div class="child"><h1 slot="header">插入标题</h1><p>插入内容</p></div>

插件

插件内部比较复杂,这里先只做简单的介绍.

1.添加全局方法或者属性,如: vue-custom-element
2.添加全局资源:指令/过滤器/过渡等,如 vue-touch
3.通过全局 mixin 方法添加一些组件选项,如: vue-router
4.添加 Vue 实例方法,通过把它们添加到 Vue.prototype 上实现。
5.一个库,提供自己的 API,同时提供上面提到的一个或多个功能,如 vue-router

混入

混入的使用:将插件的可插拔的机制发挥的淋漓尽致

选项合并

注意:
1.混入对象与自身组件components,mehtods,directives会有冲突,自身组件的属性优先级更高.
2.混入对象的钩子函数会在组件钩子函数之前调用,不会替换.

var mixin = {
  methods: {
    foo: function () {
      console.log('foo')
    },
    conflicting: function () {
      console.log('from mixin')
    }
  }
}

var vm = new Vue({
  mixins: [mixin],
  methods: {
    bar: function () {
      console.log('bar')
    },
    conflicting: function () {
      console.log('from self')
    }
  }
})

vm.foo() // => "foo"
vm.bar() // => "bar"
vm.conflicting() // => "from self"
全局混入

一旦使用全局混入对象,将会影响到 所有 之后创建的 Vue 实例.

Vue.mixin({
  created: function () {
    var myOption = this.$options.myOption
    if (myOption) {
      console.log(myOption)
    }
  }
})
new Vue({
  myOption: 'hello!'
})
// => "hello!"

创建

当我们创建一个MyPlugin的插件,我会添加一些操作

MyPlugin.install = function (Vue, options) {
  Vue.myGlobalMethod = function () {
  }

  Vue.prototype.$myMethod = function (methodOptions) {
  }
  Vue.mixin({
    created: function () {
    }
  })
}

使用

使用之前请调用use 方法

import MyPlugin from 'XXX';

Vue.use(MyPlugin, { someOption: true })

vue-router

vuerouter使用了hashurl进行路由,这种方式浏览器不会重新请求新的url.

配置

routes 中可以设置对应路由展现对应的组件

import Router from 'vue-router'

import Foo from 'XXX'
import Bar from 'XXX'

const routes = [
  { path: '/foo', component: Foo },
  { path: '/bar', component: Bar }
]

let router = new Router({routes})

new Vue ({
    router
})

路由参数

当一个视图跳转到另一个视图可能需要一些参数,我们可以获取路由当中的参数.

设置当前的参数

const routes = [
    {
        path:'/foo/id/:id/name/:name',
        component:Foo
    }
]

获取参数

const Foo = {
    template:'<div>{{$route.params.id}}</div>'
}

路由的watcher

watch

通过watch我们可以观察,route的变化

const Foo = {
  template: '...',
  watch: {
    '$route' (to, from) {
        //to目的路由 from 原路由
    }
  }
}
钩子函数
const User = {
  template: '...',
  beforeRouteUpdate (to, from, next) {
    // react to route changes...
    // 别忘记调用next()函数
    next()
  }
}

嵌套路由

meta

我们可能需要一些route的额外信息,那么就可以将其存入到meta字段里

new Router(
        routes:[{
            path: "/routea",
            name: "routea",
            component: routeA,
            meta:{
                keepAlive:false
            }
        }]
);  

我们便可以这样访问其数据信息.

$route.meta.keepAlive

嵌套路由

有一种情况我们可能需要在当前的路由当中再进行一次路由,注意这个和跳转是不一样的,路由分为父子路由.

const router = new VueRouter({
  routes: [
    { path: '/user/:id', component: User,
      children: [
        {
        //路由地址 /user/:id/posts
          path: 'posts',
          component: UserPosts
        },
        //实现默认路由
        { path: '', component: UserHome },
      ]
    }
  ]
})

场景:左侧导航栏与右侧展示页面,我们可以使用这种路由配置进行页面展示.

路由跳转

声明式跳转:

<router-link :to="/user">

编程式跳转:

router.push({ name: 'user', params: { userId: 123 }})

后退与前进:

router.go(-1);
router.go(1);

页面刷新,但是不存入浏览历史

router.replace(location, onComplete?, onAbort?)
<router-link :to="..." replace>

场景:声明式跳转相当于声明一个a标签,点击后进行路由的跳转,当然也可以自己实现相同的功能.

命名路由以及命名视图

声明route规则时,可以指定名字字段.

const router = new VueRouter({
  routes: [
    {
      path: '/user/:userId',
      name: 'user',
      component: User
    }
  ]
})

跳转执行代码

router.push({ name: 'user', params: { userId: 123 }});
<router-link :to="{ name: 'user', params: { userId: 123 }}">User</router-link>

当一个页面有多个视图时,我们需要命名视图来告知渲染正确的组件.

const router = new VueRouter({
  routes: [
    {
      path: '/',
      components: {
        default: Foo,
        a: Bar,
        b: Baz
      }
    }
  ]
})
<router-view class="view one"></router-view>
<router-view class="view two" name="a"></router-view>
<router-view class="view three" name="b"></router-view>

keep-alive

keep-alive时我们可以将组件进行缓存.

<keep-alive><component></component></keep-alive>

部分页面的缓存

我们可以结合vue-router进行缓存相应的跳转页面.这样会将所有的跳转页面不需要这样做,如何对部分页面进行缓存.

new Router({
    routes:[
        {
            path: "/routea",
            name: "routea",
            component: routeA,
            meta:{
                keepAlive:false
            }
        },
        {
            path: "/routeb",
            name: "routeb",
            component: routeB,
            meta:{
                keepAlive:true
            }
        }
})
<keep-alive>
          <router-view v-if="$route.meta.keepAlive">
          </router-view>
</keep-alive>
        <router-view v-if="!$route.meta.keepAlive">
        </router-view>

这样在读取了meta配置的原信息后,会决定是否渲染带有缓存的组件.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值