vue基础知识入门级总结__Vue.js
发布于 4 年前 作者 banyungong 1284 次浏览 来自 分享
粉丝福利 : 关注VUE中文社区公众号,回复视频领取粉丝福利

@TOC

1.vue-cli3快速创建项目

  • 1.全局安装 npm install -g @vue/cli 或 yarn global add @vue/cli
  • 2.查看版本/是否安装成功 vue -V
  • 3.创建项目
  • vue create <Project Name> //文件名 不支持驼峰(含大写字母) 在这里插入图片描述在这里插入图片描述
	? Check the features needed for your project: (Press <space> to select, <a> to toggle all, <i> to invert selection)
	>( ) Babel //转码器,可以将ES6代码转为ES5代码,从而在现有环境执行。
	( ) TypeScript// TypeScript是一个JavaScript(后缀.js)的超集(后缀.ts)包含并扩展了 JavaScript 的语法,需要被编译输出为 	JavaScript在浏览器运行,目前较少人再用
	( ) Progressive Web App (PWA) Support// 渐进式Web应用程序
	( ) Router // vue-router(vue路由)
	( ) Vuex // vuex(vue的状态管理模式)
	( ) CSS Pre-processors // CSS 预处理器(如:less、sass)
	( ) Linter / Formatter // 代码风格检查和格式化(如:ESlint)
	( ) Unit Testing // 单元测试(unit tests)
	( ) E2E Testing // e2e(end to end) 测试

在这里插入图片描述 参考引用:vue-cli3.0项目快速搭建详解

2.项目结构

在这里插入图片描述

在这里插入图片描述

3.vue实例

每个 Vue 应用程序都是通过 Vue 函数创建出一个新的 Vue 实例开始的:

var vm = new Vue({
  // 选项
})
<template>
  <div id="app">
    <router-view/>
  </div>
</template>

<script>
export default {
  name: 'App'
}
</script>
<style scoped>

</style>
new Vue({
    router,
    store,
    render: h => h(App),
}).$mount('#app');

在这里插入图片描述

4.模板语法

	<span>Message: {{ msg }}</span>
	<span v-once>这个将不会改变: {{ msg }}</span>  // 通过使用 v-once 指令,你也能执行一次性地插值,当数据改变时,插值处的内容不会更新

双大括号会将数据解释为普通文本,而非 HTML 代码。为了输出真正的 HTML,你需要使用 v-html 指令:

	<p>Using v-html directive: <span v-html="rawHtml"></span></p>

Mustache 语法不能作用在 HTML attribute 上,遇到这种情况应该使用 v-bind 指令:

	<div v-bind:id="dynamicId"></div>

使用 JavaScript 表达式

	{{ number + 1 }}
    {{ ok ? 'YES' : 'NO' }}

指令:

	 v-if 
	 v-for
	 v-on 缩写@click
	 v-bind 缩写:

动态参数

	<a v-on:[eventName]="doSomething"> ... </a>
	在这个示例中,当 eventName 的值为 "focus" 时,v-on:[eventName] 将等价于 v-on:focus。

修饰符

	.stop - 调用 event.stopPropagation()。
	.prevent - 调用 event.preventDefault()。
	.capture - 添加事件侦听器时使用 capture 模式。
	.self - 只当事件是从侦听器绑定的元素本身触发时才触发回调。
	.{keyCode | keyAlias} - 只当事件是从特定键触发时才触发回调。
	.native - 监听组件根元素的原生事件。
	.once - 只触发一次回调。
	.left - (2.2.0) 只当点击鼠标左键时触发。
	.right - (2.2.0) 只当点击鼠标右键时触发。
	.middle - (2.2.0) 只当点击鼠标中键时触发。
	.passive - (2.3.0) 以 { passive: true } 模式添加侦听器

5.生命周期

每个 Vue 实例在被创建之前,都要经过一系列的初始化过程 - 例如,Vue 实例需要设置数据观察(set up data observation)、编译模板(compile the template)、在 DOM 挂载实例(mount the instance to the DOM),以及在数据变化时更新 DOM(update the DOM when data change)。在这个过程中,Vue 实例还会调用执行一些生命周期钩子函数,这样用户能够在特定阶段添加自己的代码。 在这里插入图片描述

6.vue-router

SPA(single page application):单一页面应用程序,只有一个完整的页面;它在加载页面时,不会加载整个页面,而是只更新某个指定的容器中内容。单页面应用(SPA)的核心之一是: 更新视图而不重新请求页面;vue-router在实现单页面前端路由时,提供了两种方式:Hash模式和History模式;根据mode参数来决定采用哪一种方式。

  • Hash模式
  • History模式

History模式url中的/#去掉,变好看一点,需要把其他不符合要求的路由值定位到主页上来,要不然就直接404,这个功能要后台来配置

6.1 vue-router使用方式

  • 1:下载 npm i vue-router -S
  • 2:在main.js中引入 import VueRouter from ‘vue-router’;
  • 3:安装插件Vue.use(VueRouter);
  • 4:创建路由对象并配置路由规则 let router = new VueRouter({routes:[{path:’/home’,component:Home}]});
  • 5:将其路由对象传递给Vue的实例,options中加入 router:router
  • 6:在app.vue中留坑<router-view></router-view>

router.js

import Vue from 'vue';
import VueRouter from 'vue-router';
//安装插件
Vue.use(VueRouter); //挂载属性
//创建路由对象并配置路由规则
export default new VueRouter({
    routes: [
        //一个个对象
        {
            path: 'index',
            component: () => import('@/views/first/index'),
            name: 'index'
        }
    ]
});

main.js

import router from './router';
new Vue({
    router,
    store,
    render: h => h(App),
}).$mount('#app');

app.vue中“留坑”

<template>
  <div id="app">
    <!-- 留坑,非常重要 -->
    <router-view/>
  </div>
</template>

<script>
export default {
  name: 'App'
}
</script>
<style scoped>

</style>

6.2 vue-router 子路由嵌套

router.js

import Vue from 'vue'
import Router from 'vue-router'

Vue.use(Router);

export default new Router({
  routes: [
    {
      path: '/first',
      name: 'first',
      component: () => import('@/views/index'),
      children: [
        {
          path: 'login',
          name: 'login',
          component: () => import('@/views/login')
        },
        {
          path: 'register',
          name: 'register',
          component: () => import('@/views/register')
        }
      ]
    }
  ]
})

index.vue <router-view></router-view> 这时用来渲染匹配到的路由组件的

<template>
  <article class="index__container">
    <h1>首页</h1>
    <router-link to="/first/login">登录</router-link>
    <router-link to="/first/register">注册</router-link>
    <router-view></router-view>
  </article>
</template>

首页: 在这里插入图片描述 点击登录tab: 在这里插入图片描述 点击注册tab: 在这里插入图片描述

6.3 路由导航两种方式

  • 标签导航
	//跳转到名为user路由,并传递参数userId
	<router-link :to="/user/123"></router-link>
	或者
	<router-link :to="{ name: 'user', params: { userId: 123 }}">User</router-link>
  • 编程式导航:
	router.push('home')
    router.push({path: 'home'}) // 和上面等价
    router.push({name: 'user',params: {userId: 123}}) // 这个是命名路由    // user/123
    router.push({path: 'register',query: {plan: 'private'}})     // '/register?plan=private'
	使用router.replace(location)和router.push相似,只不过这里不会产生浏览记录
	使用router.go(n) 

命名路由:

命名路由是用来给懒人用的,给router-link传递to属性,使用path很长,很难写,所以,起个名字,方便写
当某个路由配置是
const router = new VueRouter({
    routes: [
        {
            path: '/user/:userId',
            name: 'user',
            component: User
        }
    ]
})
正常人是这样访问的 <router-link :to="/user/123"></router-link>
懒人是这样访问的 <router-link :to="{name: 'user',params: {userId: 123}}"></router-link>

6.4 命名视图

	当匹配到一个路由值,同时渲染多个组件,很简单,看下面demo
	<router-view></router-view> //这个没有起名的默认就是 default
	<router-view name="b"></router-view>
	<router-view name="c"></router-view>
	const router = new VueRouter({
	    routes: [
	        {
	            path: '/',
	            components: {
	                default: RA,
	                b: RB,
	                c: RC
	            }
	        }
	    ]
	})
	// 这样同时就渲染出 RA,RB,RC三个组件了

6.5 重定向和别名

重定向就是当访问一个路由值,定向到另外一个路由值,简单demo如下

import Vue from 'vue'
import Router from 'vue-router'
import Layout from '@/views/layout/Layout';
Vue.use(Router);

export default new Router({
  routes: [
    {
        path: '/first',
	    name: 'first',
	    redirect: '/first/index',
	    component: Layout,
	    meta: {
	        title: '首页'
	    },
	    children: [
	        {
	            path: 'index',
	            component: () => import('@/views/first/index'),
	            name: 'index',
	            alias: 'demo'
	        }
	    ]
    }
  ]
})


6.6 导航钩子

有全局的,单个路由的,组件的
1.全局的钩子,注册一个全局的before钩子
	const router = new VueRouter({...});
	router.beforeEach((to,from,next) => {
	    // 可以注册多个before,多个before之间是异步的,但是导航必须等到这些钩子执行完成,才开始
	    // to 目标路由对象
	    // from 当前路由对象
	    // next 有如下几种用法
	    // next() 执行下一个钩子函数,没有钩子,则to到目标路由
	    // next(false) 不to了,直接留在from这个路由
	    // next('/') 不管这个to了,另找了一个to
	    // next方法必须调用,不调用就是死循环
	})
	注册一个after钩子,这个作用不大,毕竟路由都跳转了,唯一的作用就是来看看而已
	router.afterEach(route => {
	    // ...
	})
2.单个路由的
	const router = new VueRouter({
	    routes: [{
	        path: '/first',
	        component: () => import('@/views/first/index'),
	        beforeEnter: (to,from,next) => {
	            //...
	        }
	    }]
	})
3.组件内的
 	beforeRouteEnter (to,from,next) {
        // 这里不能直接访问当前实例this,因为实例还没有渲染,不过可以通过next来访问
        next(vm => {
            // ...
        })
    },
    beforeRouteUpdate (to,from,next) {
        // 多个路由值访问同一个组件,来回切换,组件不会刷新,那么上面的这个钩子就没有了,此时这个钩子登场
    },
    beforeRouteLeave (to,from,next) {
        
    }
 4.组件内路由监听
	 watch: {
	    $route(){
	        ...
	    }
	}

参考引用:vue-router路由详细讲解

7. 父子组件通信

  1. 通过prop实现通信
  2. 通过$ref 实现通信
  3. provide 和 inject (高阶组件/组件库用的较多)
  4. Vuex
  5. .sync 修饰符
  6. $attrs 和 $listeners
  7. $parent
  8. $root
  9. broadcast / dispatch
  10. 声明一个全局Vue实例变量 EventBus , 把所有的通信数据,事件监听都存储到这个变量上

7.1 通过prop/$emit实现通信

	 局部引入子组件
	 import Child from '@/components/Child';
	  components: {
	      Child
	  }
	  通过:message="message"  props传值  父传子传值
	 <child :message="message" @replay="replayBack"/>
	 子传父传值 --- @replay="replayBack" 父组件接收值
 	 this.$emit('replay', '子组件发送的信息')

Demo如下: parent.vue

	<template>
	  <article class="index__container">
	    <child :message="message" @replay="replayBack"/>
	    <div>{{replyMsg}}</div>
	  </article>
	</template>
	<script>
	  import Child from '@/components/Child';
	  export default {
	    name: 'index',
	    components: {
	      Child
	    },
	    data() {
	      return {
	        message: '父组件发送的信息',
	        replyMsg: ''
	      };
	    },
	    methods: {
	      replayBack(e) {
	        this.replyMsg = e;
	      }
	    }
	  };
	</script>

Child.vue子组件:

	<template>
	  <div>
	    <div>Child页面</div>
	    <div>{{message}}</div>
	    <el-button type="primary" @click="reply">回复</el-button>
	  </div>
	</template>
	<script>
	  export default {
	    name: 'Child',
	    props: {
	      message: {
	        type: String,
	        default: ''
	      }
	    },
	    data() {
	      return {};
	    },
	    methods: {
	      reply() {
	        this.$emit('replay', '子组件发送的信息')
	      }
	    }
	  }
	</script>

在这里插入图片描述

7.2 通过$ref 实现通信

如果ref用在子组件上,指向的是组件实例,可以理解为对子组件的索引,通过$ref可能获取到在子组件里定义的属性和方法; 如果ref在普通的 DOM 元素上使用,引用指向的就是 DOM 元素,通过$ref可能获取到该DOM 的属性集合,轻松访问到DOM元素;

父组件:

	 <el-button type="primary" @click="send">发送</el-button>
	 <child ref="child"/>
	 send() {
        this.$refs.child.setMessage('send的值');
      }

子组件的方法:

	 setMessage(val) {
        this.msg = val;
      }

在这里插入图片描述

7.3. provide 和 inject (高阶组件/组件库用的较多)

成对出现:provide和inject是成对出现的

作用:用于父组件向子孙组件传递数据

使用方法:provide在父组件中返回要传给下级的数据,inject在需要使用这个数据的子辈组件或者孙辈等下级组件中注入数据。

使用场景:由于vue有$parent属性可以让子组件访问父组件。但孙组件想要访问祖先组件就比较困难。通过provide/inject可以轻松实现跨级访问父组件的数据 在这里插入图片描述 parent页面:

	<template>
	  <article>
	    <div>Parent页面</div>
	    <child/>
	  </article>
	</template>
	<script>
	  import Child from '@/components/Child';
	  export default {
	    name: 'index',
	    provide: {
	      text: 'Parent组件的值'
	    },
	    components: {
	      Child
	    },
	    data() {
	      return {};
	    },
	    methods: {}
	  };
	</script>

child页面:

	<template>
	  <div>
	    <div>Child页面</div>
	    <!--grandson组件-->
	    <grandson/>
	  </div>
	</template>
	<script>
	import Grandson from '../Grandson';
	  export default {
	    name: 'Child',
	    components: {
	      Grandson
	    },
	    data() {
	      return {};
	    },
	    methods: {}
	}
	</script>

Grandson页面:

	<template>
	  <div>
	    <div>Grandson页面</div>
	    <div>{{text}}</div>
	  </div>
	</template>
	<script>
	  export default {
	    name: 'Grandson',
	    inject: ['text'],
	    data() {
	      return {};
	    },
	    methods: {}
	  }
	</script>

7.4 Vuex

VueX是适用于在Vue项目开发时使用的状态管理工具。

  1. 安装 npm i vuex -s

  2. 使用 在这里插入图片描述 data.js

	const data = {
	  state: {
	      text: ''
	  },
	  mutations: {
	      SET_TEXT: (state, text) => {
	          state.text = text;
	      }
	  },
	  actions: {
	      setText({commit}, text) {
	          commit("SET_TEXT", text);
	      }
	  }
	};
	export default data;

index.js

	import Vue from 'vue';
	import Vuex from 'vuex';
	import getters from './getters';
	import data from './modules/data';
	
	Vue.use(Vuex);
	
	
	const store = new Vuex.Store({
	    modules: {
	        data
	    },
	    getters
	});
	export default store;

main.js Vuex实例挂载到这个vue实例中

	import Vue from 'vue'
	import router from './router'
	import store from './store'
	new Vue({
	  el: '#app',
	  router,
	  store,  //store:store 和router一样,将我们创建的Vuex实例挂载到这个vue实例中
	  render: h => h(App)
	})

组件中调用

	this.$store.getters.text
	或者
   computed: {
         ...mapGetters(["text"])
    },

组件中设值

	this.$store.dispatch("setText", '11111');
  1. VueX中的核心内容

  2. state 存放状态

  3. mutations state成员操作

  4. getters 加工state成员给外界

  5. actions 异步操作

  6. modules 模块化状态管理 在这里插入图片描述

8.watch

watch的作用可以监控一个值的变换,并调用因为变化需要执行的方法。可以通过watch动态改变关联的状态。 watch的用法大致有三种:

  1. 直接写一个监听处理函数,当每次监听到 cityName 值发生改变时,执行函数。
	 watch: {
	    cityName(newName, oldName) {
	      // ...
	    }
	  }
  1. immediate和handler

这样使用watch时有一个特点,就是当值第一次绑定的时候,不会执行监听函数,只有值发生改变才会执行。如果我们需要在最初绑定值的时候也执行函数,则就需要用到immediate属性。 比如当父组件向子组件动态传值时,子组件props首次获取到父组件传来的默认值时,也需要执行函数,此时就需要将immediate设为true。 immediate表示在watch中首次绑定的时候,是否执行handler,值为true则表示在watch中声明的时候,就立即执行handler方法,值为false,则和一般使用watch一样,在数据发生变化的时候才执行handler。

	watch: {
	    cityName: {
	      handler(newName, oldName) {
	        // ...
	      },
	      immediate: true
	    }
  }
  1. deep 当需要监听一个对象的改变时,普通的watch方法无法监听到对象内部属性的改变,只有data中的数据才能够监听到变化,此时就需要deep属性对对象进行深度监听。
	new Vue({
	  el: '#root',
	  data: {
	    cityName: {id: 1, name: 'shanghai'}
	  },
	  watch: {
	    cityName: {
	      handler(newName, oldName) {
	      // ...
	    },
	    deep: true,
	    immediate: true
	    }
	  }
	})

设置deep: true 则可以监听到cityName.name的变化,此时会给cityName的所有属性都加上这个监听器,当对象属性较多时,每个属性值的变化都会执行handler。如果只需要监听对象中的一个属性值,则可以做以下优化:使用字符串的形式监听对象属性:

	watch: {
	    'cityName.name': {
	      handler(newName, oldName) {
	      // ...
	      },
	      deep: true,
	      immediate: true
	    }
  }

这样只会给对象的某个特定的属性加监听器。 数组(一维、多维)的变化不需要通过深度监听,对象数组中对象的属性变化则需要deep深度监听。

9.directive

内置的指令 (v-model 和 v-show),Vue 也允许注册自定义指令。有的情况下,对普通 DOM 元素进行底层操作,这时候就会用到自定义指令 钩子函数

一个指令定义对象可以提供如下几个钩子函数 (均为可选):

  • inserted:被绑定元素插入父节点时调用 (仅保证父节点存在,但不一定已被插入文档中)。
  • bind:只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置。
  • update:所在组件的 VNode 更新时调用,但是可能发生在其子 VNode 更新之前。指令的值可能发生了改变,也可能没有。但是你可以通过比较更新前后的值来忽略不必要的模板更新 (详细的钩子函数参数见下)。
  • componentUpdated:指令所在组件的 VNode 及其子 VNode 全部更新后调用。
  • unbind:只调用一次,指令与元素解绑时调用。

指令钩子函数会被传入以下参数:

  • el:指令所绑定的元素,可以用来直接操作 DOM 。
  • binding:一个对象,包含以下属性:
  • name:指令名,不包括 v- 前缀。
  • value:指令的绑定值,例如:v-my-directive=“1 + 1” 中,绑定值为 2。
  • oldValue:指令绑定的前一个值,仅在 update 和 componentUpdated 钩子中可用。无论值是否改变都可用。
  • expression:字符串形式的指令表达式。例如 v-my-directive=“1 + 1” 中,表达式为 “1 + 1”。
  • arg:传给指令的参数,可选。例如 v-my-directive:foo 中,参数为 “foo”。
  • modifiers:一个包含修饰符的对象。例如:v-my-directive.foo.bar 中,修饰符对象为 { foo: true,bar: true }。
  • vnode: Vue编译生成的虚拟节点。移步 VNode API 来了解更多详情。
  • oldVnode:上一个虚拟节点,仅在 update 和 componentUpdated 钩子中可用。

实例:拖拽的demo 全局定义 在这里插入图片描述

在这里插入图片描述 drag.js

	export default {
	  bind(el, binding) {
	    const div = el;
	    let is_moving = false;
	    div.onmousedown = (e) => {
	      const oDiv = e.target;        // 获取目标元素;
	      const disX = e.clientX - oDiv.offsetLeft;
	      const disY = e.clientY - oDiv.offsetTop;
	      is_moving = true;
	      document.onmousemove = (e) => {
	        let left = e.clientX - disX;
	        let top = e.clientY - disY;
	        // 移动当前元素
	        if (is_moving) {
	          if (left <= 0) {
	            left = 0;
	          } else if (left >= document.documentElement.clientWidth - oDiv.offsetWidth) {
	            // document.documentElement.clientWidth 屏幕的可视宽度
	            left = document.documentElement.clientWidth - oDiv.offsetWidth;
	          }
	          if (top <= 0) {
	            top = 0;
	          } else if (top >= document.documentElement.clientHeight - oDiv.offsetHeight) {
	            // document.documentElement.clientHeight 屏幕的可视高度
	            top = document.documentElement.clientHeight - oDiv.offsetHeight;
	          }
	          div.style.left = left + 'px';
	          div.style.top = top + 'px';
	        }
	      };
	      document.onmouseup = (e) => {
	        is_moving = false;
	        div.onmousemove = null;
	        div.onmouseup = null;
	      };
	      // return false不加的话可能导致黏连,就是拖到一个地方时div粘在鼠标上不下来,相当于onmouseup失效
	      return false;
	    };
	  },
	  unbind(el, bing) {
	
	  }
	}

index.js

	import drag from './drag';

	const plugin = {};
	plugin.install = function (Vue, options = {}) {
	  Vue.directive("drag", drag);
	};
	export default plugin;
	
	// 通过调用全局方法 Vue.use() 使用插件:

全局定义 main.js

	import drag from './directive/drag/index';
	Vue.use(drag);

页面使用:

	 <div class="index__img" v-drag></div>

局部定义指令

<template>
  <div class="hello">
  	<div v-test='name'></div>
  </div>
</template>
<script>
export default {
  data () {
    return {
     name:'我是名字',
    }
  },
  directives:{
  	test:{
	    inserted: function (el,binding) {// 指令的定义
	       / /el为绑定元素,可以对其进行dom操作
	       console.log(binding) //一个对象,包含很多属性属性
	    },
	    bind: function (el, binding, vnode) {
		    el.innerHTML =binding.value
		  }
  	}
  },
  created:function(){
  },
  mounted:function(){ 
  },
  methods:{
  }
}
</script>

10.mixins

混入 (mixin) 提供了一种非常灵活的方式,来分发 Vue 组件中的可复用功能。一个混入对象可以包含任意组件选项。当组件使用混入对象时,所有混入对象的选项将被“混合”进入该组件本身的选项。

  1. 数据对象合并 数据对象在内部会进行浅合并 (一层属性深度),在和组件的数据发生冲突时以组件数据优先
	var mixin = {
	    data() {
	        return {
	            msg_mixins: 'mixins',
	            msg: '123'
	        }
	    }
	}
	var app = new Vue({
	    mixins: [mixin],
	    el: '#app',
	    data: {
	        msg: 'app'
	    }
	})
	// app mixins
  1. 钩子函数合并 同名钩子函数将混合为一个数组,因此都将被调用。另外,混入对象的钩子将在组件自身钩子之前调用。
var mixin = {
    data() {
        return {
            msg_mixins: 'mixins',
            msg: '123'
        }
    },
    created: function () {
        console.log('混入对象的钩子被调用')
    }
}
var app = new Vue({
    mixins: [mixin],
    el: '#app',
    data: {
        msg: 'app'
    },
    created: function () {
        console.log('组件钩子被调用')
    }
})

在这里插入图片描述

  1. methods, components 和 directives合并 methods, components 和 directives,将被混合为同一个对象。两个对象键名冲突时,取组件对象的键值对。
	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"
  1. 全局混入 混入也可以进行全局注册。使用时格外小心!一旦使用全局混入,它将影响每一个之后创建的 Vue 实例。使用恰当时,这可以用来为自定义选项注入处理逻辑。
	// 直接注册
	Vue.mixin({
	  data() {
	    return {
	      globalMsg2: 'hello global mixin 2222'
	    }
	  },
	  created() {
	    console.log('模块化注册全局混入的钩子函数 2222');
	  },
	  methods: {
	    globalShow2() {
	      alert('模块化注册全局混入的钩子函数 2222');
	    }
	  }
	});

11.computed

计算属性将被混入到 Vue 实例中。所有 getter 和 setter 的 this 上下文自动地绑定为 Vue 实例。 计算属性是基于它们的响应式依赖进行缓存的。

	<div id="example">
  		<p>Original message: "{{ message }}"</p>
	  <p>Computed reversed message: "{{ reversedMessage }}"</p>
	</div>
	var vm = new Vue({
	  el: '#example',
	  data: {
	    message: 'Hello'
	  },
	  computed: {
	    // 计算属性的 getter
	    reversedMessage: function () {
	      // `this` 指向 vm 实例
	      return this.message.split('').reverse().join('')
	    }
	  }
	})

Original message: “Hello” Computed reversed message: “olleH”

计算属性的 setter 计算属性默认只有 getter,不过在需要时你也可以提供一个 setter:

	// ...
	computed: {
	  fullName: {
	    // getter
	    get: function () {
	      return this.firstName + ' ' + this.lastName
	    },
	    // setter
	    set: function (newValue) {
	      var names = newValue.split(' ')
	      this.firstName = names[0]
	      this.lastName = names[names.length - 1]
	    }
	  }
	}
	// ...

现在再运行 vm.fullName = ‘John Doe’ 时,setter 会被调用,vm.firstName 和 vm.lastName 也会相应地被更新。

12.filter

Vue.js 允许你自定义过滤器,可被用于一些常见的文本格式化。过滤器可以用在两个地方:双花括号插值和 v-bind 表达式 (后者从 2.1.0+ 开始支持)。过滤器应该被添加在 JavaScript 表达式的尾部,由“管道”符号指示:

	<!-- 在双花括号中 -->
	{{ message | capitalize }}
	
	<!-- 在 `v-bind` 中 -->
	<div v-bind:id="rawId | formatId"></div>
	filters: {
	  capitalize: function (value) {
	    if (!value) return '';
	    value = value.toString();
	    return value.charAt(0).toUpperCase() + value.slice(1);
	  }
	}

创建 Vue 实例之前全局定义过滤器:

	Vue.filter('capitalize', function (value) {
	  if (!value) return '';
	  value = value.toString();
	  return value.charAt(0).toUpperCase() + value.slice(1);
	})
	
	new Vue({
	  // ...
	})

当全局过滤器和局部过滤器重名时,会采用局部过滤器。 在这里插入图片描述 过滤器可以串联:

	{{ message | filterA | filterB }}

filterA 被定义为接收单个参数的过滤器函数,表达式 message 的值将作为参数传入到函数中。然后继续调用同样被定义为接收单个参数的过滤器函数 filterB,将 filterA 的结果传递到 filterB 中。

过滤器是 JavaScript 函数,因此可以接收参数:

	{{ message | filterA('arg1', arg2) }}

filterA 被定义为接收三个参数的过滤器函数。其中 message 的值作为第一个参数,普通字符串 ‘arg1’ 作为第二个参数,表达式 arg2 的值作为第三个参数。

版权声明:著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。 作者: 柚子8806 原文链接:https://juejin.im/post/6868130389131689992

回到顶部