您的当前位置:首页使用Vue.js有哪些注意事项
广告

使用Vue.js有哪些注意事项

2023-11-30 来源:六三科技网

这次给大家带来使用Vue.js有哪些注意事项,使用Vue.js的注意事项有哪些,下面就是实战案例,一起来看一下。

1.传递参数时,第二个参数要与前面的逗号有一个空格

window.localStorage.setItem(STORAGE_KEY, JSON.stringify(items))

2. 注意空格

正确格式

<script>import Store from './store'console.log(Store)export default { ... }</script>错误格式<script> import Store from './store' console.log(Store)export default { ... }</script>

3. 父向子组件传参

父组件中

//模板中<template> <div id="app"> //之前老版本 <conponent-a msgfromfather="父亲传给儿子!"></conponent-a> <ConponentA msgfromfather="父亲传给儿子!"></ConponentA> </div></template>//Js<script>export default { //注册ConponentA components: {ConponentA},}</script>

子组件中

<template> <div class="hello"> <h1>{{ msg }}</h1> <button v-on:click="onClickMe()">点我啊,小样儿</button> </div></template><script> export default { data () { return { msg: 'hello from component A!' } }, //props 可以是数组或对象,用于接收来自父组件的数据 props: ['msgfromfather'], methods: { onClickMe: function () { //打印从父组件传过来的值 console.log(this.msgfromfather) } } }</script><style scoped> h1 { font-weight: normal; }</style>

4. 子向父组件传参

儿子告诉父亲 需要使用vm.$emit 和vm.$on 触发事件和监听事件

子组件中

<template> <div class="hello"> <h1>{{ msg }}</h1> <h1>{{msgfromfather}}</h1> <button v-on:click="onClickMe()">点我啊,小样儿</button> </div></template><script> export default { data () { return { msg: 'hello from component A!' } }, methods: { onClickMe: function () {// 子传父 触发当前实例上的事件 this.$emit('child-tell-me-something', this.msg) } } }</script><style scoped> h1 { font-weight: normal; }</style>

父组件中

<template> <div id="app"> <p>child tells me: {{childWorlds}}</p> <ConponentA msgfromfather="父亲传给儿子!" v-on:child-tell-me-something="listenToMyBoy"></ConponentA> </div></template><script>import ConponentA from './components/componentA.vue'export default { data: function () { return { childWorlds: '' } }, components: {ConponentA}, watch: { items: { handler: function (items) { Store.save(items) }, deep: true } }, methods: { //监听 listenToMyBoy: function (msg) { console.log(msg) this.childWorlds = msg } }}</script>

除了这个方法外,还有其他方法,详见Vue.js官网

自定义组件指定属性数据类型

export default { props: { slides: { type: Array, //数组 default: [] //默认值 } },在加载完毕执行某个方法 mounted () { this.loadxxx() }

@mouseover="xxxx" 鼠标进入(执行某个事件), @mouseout="xxxx" 鼠标移出(执行某个事件);

transiotions动画对left和right等无效,要想实现动画效果,只能用x轴了;

slot 插槽

this.abc = false 等同于 this['abc'] = false

父组件style不添加scoped,这样他的子组件可以共用他的样式,也就是说,可以把子组件的样式,写在父组件中.

<!-- Add "scoped" attribute to limit CSS to this component only --><style>......</style>

& 代表父元素

<!--css书写规范 可被继承的写在前面,不让继承的的写在后面--><style lang="stylus" rel="stylesheet/stylus"> #app .tab display: flex width: 100% height: 40px line-height: 40px .tab-item flex: 1 text-align: center /* & > a & 代表父元素 tab-item 子元素选择器 */ & > a display: block font-style: 14px color: rgb(77,85,93) &.active color: rgb(240,20,20)</style>

1像素边框的实现在pc端可以通过下面的设置,来实现,

border-bottom: 1px solid rgba(7,17,27,0.1)

相信看了本文案例你已经掌握了方法,更多精彩请关注Gxl网其它相关文章!

推荐阅读:

深入JavaScript之JS的运动

深入JavaScript之DOM的高级应用

深入JavaScript之小知识点

小编还为您整理了以下内容,可能对您也有帮助:

用 vue2 进行项目开发要注意什么?

Vue.js 是一个流行的前端框架,用于构建用户界面。如果您使用 Vue.js 2 进行项目开发,以下是一些需要注意的事项:

1. 了解 Vue.js 的基本概念和语法,例如组件、指令、过滤器和计算属性等。这将有助于您更好地理解 Vue.js 的工作原理。

2. 熟悉 Vue.js 的生命周期钩子函数,例如 created、mounted 和 destroyed 等。这将有助于您更好地管理 Vue.js 实例。

3. 熟悉 Vue.js 的路由机制,例如 vue-router。这将有助于您更好地构建单页应用程序。

4. 熟悉 Vue.js 的状态管理库,例如 vuex。这将有助于您更好地管理应用程序的状态。

5. 熟悉 Vue.js 的开发工具,例如 vue-cli。这将有助于您更快地构建和管理 Vue.js 项目。

使用Vue时有哪些小技巧

这次给大家带来使用Vue时有哪些小技巧,使用Vue的注意事项有哪些,下面就是实战案例,一起来看一下。

在vue的使用过程中会遇到各种场景,当普通使用时觉得没什么,但是或许优化一下可以更高效更优美的进行开发。下面有一些我在日常开发的时候用到的小技巧,在下将不定期更新~

1. 多图表resize事件去中心化

1.1 一般情况

有时候我们会遇到这样的场景,一个组件中有几个图表,在浏览器resize的时候我们希望图表也进行resize,因此我们会在父容器组件中写:

mounted() {

setTimeout(() => window.onresize = () => {

this.$refs.chart1.chartWrapperDom.resize()

this.$refs.chart2.chartWrapperDom.resize()

// ...

}, 200)

destroyed() { window.onresize = null }这样子图表组件如果跟父容器组件不在一个页面,子组件的状态就被放到父组件进行管理,为了维护方便,我们自然希望子组件的事件和状态由自己来维护,这样在添加删除组件的时候就不需要去父组件挨个修改

1.2 优化

这里使用了lodash的节流throttle函数,也可以自己实现,这篇文章也有节流的实现可以参考一下。 以Echarts为例,在每个图表组件中:

computed: {

/**

* 图表DOM

*/

chartWrapperDom() {

const dom = document.getElementById('consume-analy-chart-wrapper')

return dom && Echarts.init(dom)

},

/**

* 图表resize节流,这里使用了lodash,也可以自己使用setTimout实现节流

*/

chartResize() {

return _.throttle(() => this.chartWrapperDom && this.chartWrapperDom.resize(), 400)

}

},

mounted() {

window.addEventListener('resize', this.chartResize)

},

destroyed() {

window.removeEventListener('resize', this.chartResize)

}2. 全局过滤器注册

2.1 一般情况

官方注册过滤器的方式:

export default {

data () { return {} },

filters:{

orderBy (){

// doSomething

},

uppercase () {

// doSomething

}

}

}但是我们做项目来说,大部分的过滤器是要全局使用的,不会每每用到就在组件里面去写,抽成全局的会更好些。官方注册全局的方式:

// 注册

Vue.filter('my-filter', function (value) {

// 返回处理后的值

})

// getter,返回已注册的过滤器

var myFilter = Vue.filter('my-filter')但是分散写的话不美观,因此可以抽出成单独文件。

2.2 优化

我们可以抽出到文件,然后使用Object.keys在main.js入口统一注册 /src/common/filters.js

let dateServer = value => value.replace(/(d{4})(d{2})(d{2})/g, '$1-$2-$3')

export { dateServer }

/src/main.js

import * as custom from './common/filters/custom'

Object.keys(custom).forEach(key => Vue.filter(key, custom[key]))然后在其他的.vue 文件中就可愉快地使用这些我们定义好的全局过滤器了

<template>

<section class="content">

<p>{{ time | dateServer }}</p> <!-- 2016-01-01 -->

</section>

</template>

<script>

export default {

data () {

return {

time: 20160101

}

}

}

</script>3. 全局组件注册

3.1 一般情况

需要使用组件的场景:

<template>

<BaseInput v-model="searchText" @keydown.enter="search"/>

<BaseButton @click="search">

<BaseIcon name="search"/>

</BaseButton>

</template>

<script>

import BaseButton from './baseButton'

import BaseIcon from './baseIcon'

import BaseInput from './baseInput'

export default {

components: { BaseButton, BaseIcon, BaseInput }

}

</script>我们写了一堆基础UI组件,然后每次我们需要使用这些组件的时候,都得先import,然后声明components,很繁琐,这里可以使用统一注册的形式

3.2 优化

我们需要借助一下神器webpack,使用 require.context() 方法来创建自己的 模块 上下文,从而实现自动动态require组件。这个方法需要3个参数:要搜索的文件夹目录、是否还应该搜索它的子目录、以及一个匹配文件的正则表达式。 我们在components文件夹添加一个叫componentRegister.js的文件,在这个文件里借助webpack动态将需要的基础组件统统打包进来。 /src/components/componentRegister.js

import Vue from 'vue'

/**

* 首字母大写

* @param str 字符串

* @example heheHaha

* @return {string} HeheHaha

*/

function capitalizeFirstLetter(str) {

return str.charAt(0).toUpperCase() + str.slice(1)

}

/**

* 对符合'xx/xx.vue'组件格式的组件取组件名

* @param str fileName

* @example abc/bcd/def/basicTable.vue

* @return {string} BasicTable

*/

function validateFileName(str) {

return /^S+.vue$/.test(str) &&

str.replace(/^S+/(w+).vue$/, (rs, $1) => capitalizeFirstLetter($1))

}

const requireComponent = require.context('./', true, /.vue$/)

// 找到组件文件夹下以.vue命名的文件,如果文件名为index,那么取组件中的name作为注册的组件名

requireComponent.keys().forEach(filePath => {

const componentConfig = requireComponent(filePath)

const fileName = validateFileName(filePath)

const componentName = fileName.toLowerCase() === 'index'

? capitalizeFirstLetter(componentConfig.default.name)

: fileName

Vue.component(componentName, componentConfig.default || componentConfig)

})这里文件夹结构:

components

│ componentRegister.js

├─BasicTable

│ BasicTable.vue

├─MultiCondition

│ index.vue这里对组件名做了判断,如果是index的话就取组件中的name属性处理后作为注册组件名,所以最后注册的组件为: multi-condition 、 basic-table 最后我们在main.js中import 'components/componentRegister.js',然后我们就可以随时随地使用这些基础组件,无需手动引入了~

4. 不同路由的组件复用

4.1 场景还原

当某个场景中vue-router从/post-page/a,跳转到/post-page/b。然后我们惊人的发现,页面跳转后数据竟然没更新?!原因是vue-router"智能地"发现这是同一个组件,然后它就决定要复用这个组件,所以你在created函数里写的方法压根就没执行。通常的解决方案是监听$route的变化来初始化数据,如下:

data() {

return {

loading: false,

error: null,

post: null

}

},

watch: {

'$route': { // 使用watch来监控是否是同一个路由

handler: 'resetData',

immediate: true

}

},

methods: {

resetData() {

this.loading = false

this.error = null

this.post = null

this.getPost(this.$route.params.id)

},

getPost(id){ }

}4.2 优化

那要怎么样才能实现这样的效果呢,答案是给 router-view 添加一个不同的key,这样即使是公用组件,只要url变化了,就一定会重新创建这个组件。

<router-view :key="$route.fullpath"></router-view>还可以在其后加 + +new Date() 时间戳,保证独一无二

5. 高阶组件

5.1 一般情况

// 父组件

<BaseInput :value="value"

label="密码"

placeholder="请填写密码"

@input="handleInput"

@focus="handleFocus">

</BaseInput>

// 子组件

<template>

<label>

{{ label }}

<input :value=" value"

:placeholder="placeholder"

@focus="$emit('focus', $event)"

@input="$emit('input', $event.target.value)">

</label>

</template>5.2 优化

1 每一个从父组件传到子组件的props,我们都得在子组件的Props中显式的声明才能使用。这样一来,我们的子组件每次都需要申明一大堆props, 而类似placeholer这种dom原生的property我们其实完全可以使用 $attrs 直接从父传到子,无需声明。方法如下:

<input :value="value"

v-bind="$attrs"

@input="$emit('input', $event.target.value)">$attrs 包含了父作用域中不作为 prop 被识别 (且获取) 的特性绑定 (class 和 style 除外)。当一个组件没有声明任何 prop 时,这里会包含所有父作用域的绑定,并且可以通过 v-bind="$attrs" 传入内部组件——在创建更高层次的组件时非常有用。

2 注意到子组件的 @focus="$emit('focus', $event)" 其实什么都没做,只是把event传回给父组件而已,那其实和上面类似,完全没必要显式地申明:

<input :value="value"

v-bind="$attrs"

v-on="listeners"/>

computed: {

listeners() {

return {

...this.$listeners,

input: event =>

this.$emit('input', event.target.value)

}

}

}$listeners 包含了父作用域中的 (不含 .native 修饰器的)v-on 事件。它可以通过 v-on="$listeners" 传入内部组件——在创建更高层次的组件时非常有用。

需要注意的是,由于我们input并不是BaseInput这个组件的根节点,而默认情况下父作用域的不被认作 props 的特性绑定将会“回退”且作为普通的 HTML 特性应用在子组件的根元素上。所以我们需要设置 inheritAttrs: false ,这些默认行为将会被去掉,以上两点的优化才能成功。

6. 路由根据开发状态懒加载

6.1 一般情况

一般我们在路由中加载组件的时候:

import Login from '@/views/login.vue'

export default new Router({

routes: [{ path: '/login', name: '登陆', component: Login}]

})当你需要懒加载 lazy-loading 的时候,需要一个个把routes的component改为 () => import('@/views/login.vue') ,甚为麻烦。

当你的项目页面越来越多之后,在开发环境之中使用 lazy-loading 会变得不太合适,每次更改代码触发热更新都会变得非常的慢。所以建议只在生成环境之中使用路由懒加载功能。

6.2 优化

根据Vue的异步组件和Webpack的代码分割功能可以轻松实现组件的懒加载,如:

const Foo = () => import('./Foo.vue')

在区分开发环境与生产环境时,可以在路由文件夹下分别新建两个文件: _import_proction.js

mole.exports = file => () => import('@/views/' + file + '.vue')

_import_development.js ,这种写法 vue-loader 版本至少v13.0.0以上

mole.exports = file => require('@/views/' + file + '.vue').default

而在设置路由的 router/index.js 文件中:

const _import = require('./_import_' + process.env.NODE_ENV)

export default new Router({

routes: [{ path: '/login', name: '登陆', component: _import('login/index') }]

})这样组件在开发环境下就是非懒加载,生产环境下就是懒加载的了

7 vue-loader小技巧

vue-loader 是处理 *.vue 文件的 webpack loader。它本身提供了丰富的 API,有些 API 很实用但很少被人熟知。例如接下来要介绍的 preserveWhitespace 和 transformToRequire

7.1 用 preserveWhitespace 减少文件体积

有些时候我们在写模板时不想让元素和元素之间有空格,可能会写成这样:

<ul>

<li>1111</li><li>2222</li><li>333</li>

</ul>当然还有其他方式,比如设置字体的 font-size: 0 ,然后给需要的内容单独设置字体大小,目的是为了去掉元素间的空格。其实我们完全可以通过配置 vue-loader 实现这一需求。

{

vue: {

preserveWhitespace: false

}

}它的作用是阻止元素间生成空白内容,在 Vue 模板编译后使用 _v(" ") 表示。如果项目中模板内容多的话,它们还是会占用一些文件体积的。例如 Element 配置该属性后,未压缩情况下文件体积减少了近 30Kb。

7.2 使用 transformToRequire 再也不用把图片写成变量了

以前在写 Vue 的时候经常会写到这样的代码:把图片提前 require 传给一个变量再传给组件。

<template>

<p>

<avatar :default-src="DEFAULT_AVATAR"></avatar>

</p>

</template>

<script>

export default {

created () {

this.DEFAULT_AVATAR = require('./assets/default-avatar.png')

}

}

</script>其实通过配置 transformToRequire 后,就可以直接配置,这样vue-loader会把对应的属性自动 require 之后传给组件

{

vue: {

transformToRequire: {

avatar: ['default-src']

}

}

}于是我们代码就可以简化不少

<template>

<p>

<avatar default-src="./assets/default-avatar.png"></avatar>

</p>

</template>在 vue-cli 的 webpack 模板下,默认配置是:

transformToRequire: {

video: ['src', 'poster'],

source: 'src',

img: 'src',

image: 'xlink:href'

}可以举一反三进行一下类似的配置

vue-loader 还有很多实用的 API 例如最近加入的自定义块,感兴趣的各位可以去文档里找找看。

8. render 函数

在某些场景下你可能需要render 渲染函数带来的完全编程能力来解决不太容易解决的问题,特别是要动态选择生成标签和组件类型的场景。

8.1 动态标签

1. 一般情况

比如根据props来生成标签的场景

<template>

<p>

<p v-if="level =

Vue.js提升必知的几点总结

这次给大家带来Vue.js提升必知的几点总结,Vue.js提升的注意事项有哪些,下面就是实战案例,一起来看一下。

第一招:化繁为简的Watchers

场景还原:

created(){

this.fetchPostList()

},

watch: {

searchInputValue(){

this.fetchPostList()

}

}

组件创建的时候我们获取一次列表,同时监听input框,每当发生变化的时候重新获取一次筛选后的列表这个场景很常见,有没有办法优化一下呢?

招式解析:

首先,在watchers中,可以直接使用函数的字面量名称;其次,声明immediate:true表示创建组件时立马执行一次。

watch: {

searchInputValue:{

handler: 'fetchPostList',

immediate: true

}

}

第二招:一劳永逸的组件注册

场景还原:

import BaseButton from './baseButton'

import BaseIcon from './baseIcon'

import BaseInput from './baseInput'

export default {

components: {

BaseButton,

BaseIcon,

BaseInput

}

}<BaseInput

v-model="searchText"

@keydown.enter="search"

/>

<BaseButton @click="search">

<BaseIcon name="search"/>

</BaseButton>

我们写了一堆基础UI组件,然后每次我们需要使用这些组件的时候,都得先import,然后声明components,很繁琐!秉持能偷懒就偷懒的原则,我们要想办法优化!

招式解析:

我们需要借助一下神器webpack,使用 require.context() 方法来创建自己的(模块)上下文,从而实现自动动态require组件。这个方法需要3个参数:要搜索的文件夹目录,是否还应该搜索它的子目录,以及一个匹配文件的正则表达式。

我们在components文件夹添加一个叫global.js的文件,在这个文件里借助webpack动态将需要的基础组件统统打包进来。

import Vue from 'vue'

function capitalizeFirstLetter(string) {

return string.charAt(0).toUpperCase() + string.slice(1)

}

const requireComponent = require.context(

'.', false, /.vue$/

//找到components文件夹下以.vue命名的文件

)

requireComponent.keys().forEach(fileName => {

const componentConfig = requireComponent(fileName)

const componentName = capitalizeFirstLetter(

fileName.replace(/^.//, '').replace(/.w+$/, '')

//因为得到的filename格式是: './baseButton.vue', 所以这里我们去掉头和尾,只保留真正的文件名

)

Vue.component(componentName, componentConfig.default || componentConfig)

})

最后我们在main.js中import 'components/global.js',然后我们就可以随时随地使用这些基础组件,无需手动引入了。

第三招:釜底抽薪的router key

场景还原:

下面这个场景真的是伤透了很多程序员的心...先默认大家用的是Vue-router来实现路由的控制。

假设我们在写一个博客网站,需求是从/post-page/a,跳转到/post-page/b。然后我们惊人的发现,页面跳转后数据竟然没更新?!原因是vue-router"智能地"发现这是同一个组件,然后它就决定要复用这个组件,所以你在created函数里写的方法压根就没执行。通常的解决方案是监听$route的变化来初始化数据,如下:

data() {

return {

loading: false,

error: null,

post: null

}

},

watch: {

'$route': {

handler: 'resetData',

immediate: true

}

},

methods: {

resetData() {

this.loading = false

this.error = null

this.post = null

this.getPost(this.$route.params.id)

},

getPost(id){

}

}

bug是解决了,可每次这么写也太不优雅了吧?秉持着能偷懒则偷懒的原则,我们希望代码这样写:

data() {

return {

loading: false,

error: null,

post: null

}

},

created () {

this.getPost(this.$route.params.id)

},

methods () {

getPost(postId) {

// ...

}

}

招式解析:

那要怎么样才能实现这样的效果呢,答案是给router-view添加一个unique的key,这样即使是公用组件,只要url变化了,就一定会重新创建这个组件。(虽然损失了一丢丢性能,但避免了无限的bug)。同时,注意我将key直接设置为路由的完整路径,一举两得。

<router-view :key="$route.fullpath"></router-view>

第四招: 无所不能的render函数

场景还原:

vue要求每一个组件都只能有一个根元素,当你有多个根元素时,vue就会给你报错

<template>

<li

v-for="route in routes"

:key="route.name"

>

<router-link :to="route">

{{ route.title }}

</router-link>

</li>

</template>

ERROR - Component template should contain exactly one root element.

If you are using v-if on multiple elements, use v-else-if

to chain them instead.

招式解析:

那有没有办法化解呢,答案是有的,只不过这时候我们需要使用render()函数来创建HTML,而不是template。其实用js来生成html的好处就是极度的灵活功能强大,而且你不需要去学习使用vue的那些功能有限的指令API,比如v-for,

v-if。(reactjs就完全丢弃了template)

functional: true,

render(h, { props }) {

return props.routes.map(route =>

<li key={route.name}>

<router-link to={route}>

{route.title}

</router-link>

</li>

)

}

第五招:无招胜有招的高阶组件

划重点:这一招威力无穷,请务必掌握

当我们写组件的时候,通常我们都需要从父组件传递一系列的props到子组件,同时父组件监听子组件emit过来的一系列事件。举例子:

//父组件

<BaseInput

:value="value"

label="密码"

placeholder="请填写密码"

@input="handleInput"

@focus="handleFocus>

</BaseInput>

//子组件

<template>

<label>

{{ label }}

<input

:value="value"

:placeholder="placeholder"

@focus=$emit('focus', $event)"

@input="$emit('input', $event.target.value)"

>

</label>

</template>

有下面几个优化点:

1.每一个从父组件传到子组件的props,我们都得在子组件的Props中显式的声明才能使用。这样一来,我们的子组件每次都需要申明一大堆props,

而类似placeholer这种dom原生的property我们其实完全可以直接从父传到子,无需声明。方法如下:

<input

:value="value"

v-bind="$attrs"

@input="$emit('input', $event.target.value)"

>

$attrs包含了父作用域中不作为 prop 被识别 (且获取) 的特性绑定 (class 和 style 除外)。当一个组件没有声明任何

prop 时,这里会包含所有父作用域的绑定,并且可以通过 v-bind="$attrs" 传入内部组件——在创建更高层次的组件时非常有用。

2.注意到子组件的@focus=$emit('focus', $event)"其实什么都没做,只是把event传回给父组件而已,那其实和上面类似,我完全没必要显式地申明:

<input

:value="value"

v-bind="$attrs"

v-on="listeners"

>

computed: {

listeners() {

return {

...this.$listeners,

input: event =>

this.$emit('input', event.target.value)

}

}

}

$listeners包含了父作用域中的 (不含 .native 修饰器的) v-on 事件。它可以通过 v-on="$listeners" 传入内部组件——在创建更高层次的组件时非常有用。

3.需要注意的是,由于我们input并不是BaseInput这个组件的根节点,而默认情况下父作用域的不被认作 props

的特性绑定将会“回退”且作为普通的 HTML

特性应用在子组件的根元素上。所以我们需要设置inheritAttrs:false,这些默认行为将会被去掉, 以上两点的优化才能成功。

相信看了本文案例你已经掌握了方法,更多精彩请关注Gxl网其它相关文章!

推荐阅读:

vue的新手入门教程

Vue项目怎样分环境打包

如何使用Vue.js计算属性与侦听器

这次给大家带来如何使用Vue.js计算属性与侦听器,使用Vue.js计算属性与侦听器的注意事项有哪些,下面就是实战案例,一起来看一下。

一、 概述

计算属性

模板内的表达式非常便利,但是设计它们的初衷是用于简单运算的。在模板中放入太多的逻辑会让模板过重且难以维护。例如:

<p id="example">

{{ message.split('').reverse().join('') }}

</p> 在这个地方,模板不再是简单的声明式逻辑。你必须看一段时间才能意识到,这里是想要显示变量 message 的翻转字符串。当你想要在模板中多次引用此处的翻转字符串时,就会更加难以处理。

所以,对于任何复杂逻辑,你都应当使用计算属性。

基础例子

<p id="example">

<p>Original message: "{{ message }}"</p>

<p>Computed reversed message: "{{ reversedMessage }}"</p>

</p>

var vm = new Vue({

el: '#example',

data: {

message: 'Hello'

},

computed: {

// 计算属性的 getter

reversedMessage: function () {

// `this` 指向 vm 实例

return this.message.split('').reverse().join('')

}

}

}) 结果:

这里我们声明了一个计算属性 reversedMessage。我们提供的函数将用作属性 vm.reversedMessage 的 getter 函数

console.log(vm.reversedMessage) // => 'olleH'

vm.message = 'Goodbye'

console.log(vm.reversedMessage) // => 'eybdooG' 你可以像绑定普通属性一样在模板中绑定计算属性。Vue 知道 vm.reversedMessage 依赖于 vm.message,因此当 vm.message 发生改变时,所有依赖 vm.reversedMessage 的绑定也会更新。而且最妙的是我们已经以声明的方式创建了这种依赖关系:计算属性的 getter 函数是没有副作用 (side effect) 的,这使它更易于测试和理解。

二、计算属性缓存 vs 方法

你可能已经注意到我们可以通过在表达式中调用方法来达到同样的效果

<p>Reversed message: "{{ reversedMessage() }}"</p>

// 在组件中

methods: {

reversedMessage: function () {

return this.message.split('').reverse().join('')

}

} 我们可以将同一函数定义为一个方法而不是一个计算属性。两种方式的最终结果确实是完全相同的。然而,不同的是计算属性是基于它们的依赖进行缓存的。计算属性只有在它的相关依赖发生改变时才会重新求值。这就意味着只要 message 还没有发生改变,多次访问 reversedMessage 计算属性会立即返回之前的计算结果,而不必再次执行函数。

这也同样意味着下面的计算属性将不再更新,因为 Date.now() 不是响应式依赖

computed: {

now: function () {

return Date.now()

}

} 相比之下,每当触发重新渲染时,调用方法将总会再次执行函数。

我们为什么需要缓存?

假设我们有一个性能开销比较大的的计算属性 A,它需要遍历一个巨大的数组并做大量的计算。然后我们可能有其他的计算属性依赖于 A 。如果没有缓存,我们将不可避免的多次执行 A 的 getter!如果你不希望有缓存,请用方法来替代。

三、计算属性 vs 侦听属性

Vue 提供了一种更通用的方式来观察和响应 Vue 实例上的数据变动:侦听属性。当你有一些数据需要随着其它数据变动而变动时,你很容易滥用 watch——特别是如果你之前使用过 AngularJS。然而,通常更好的做法是使用计算属性而不是命令式的 watch 回调。

细想一下这个例子

<p id="demo">{{ fullName }}</p>

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

}

}

}) 上面代码是命令式且重复的。将它与计算属性的版本进行比较:

var vm = new Vue({

el: '#demo',

data: {

firstName: 'Foo',

lastName: 'Bar'

},

computed: {

fullName: function () {

return this.firstName + ' ' + this.lastName

}

}

}) 是不是好多了。

四、计算属性的 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 也会相应地被更新。

五、侦听器

虽然计算属性在大多数情况下更合适,但有时也需要一个自定义的侦听器。这就是为什么 Vue 通过 watch 选项提供了一个更通用的方法,来响应数据的变化。当需要在数据变化时执行异步或开销较大的操作时,这个方式是最有用的。

例如:

<p id="watch-example">

<p>

Ask a yes/no question:

<input v-model="question">

</p>

<p>{{ answer }}</p>

</p>

<!-- 因为 AJAX 库和通用工具的生态已经相当丰富,Vue 核心代码没有重复 -->

<!-- 提供这些功能以保持精简。这也可以让你自由选择自己更熟悉的工具。 -->

<script src="https://cdn.jsdelivr.net/npm/axios@0.12.0/dist/axios.min.js"></script>

<script src="https://cdn.jsdelivr.net/npm/lodash@4.13.1/lodash.min.js"></script>

<script>

var watchExampleVM = new Vue({

el: '#watch-example',

data: {

question: '',

answer: 'I cannot give you an answer until you ask a question!'

},

watch: {

// 如果 `question` 发生改变,这个函数就会运行

question: function (newQuestion, oldQuestion) {

this.answer = 'Waiting for you to stop typing...'

this.getAnswer()

}

},

methods: {

// `_.debounce` 是一个通过 Lodash 操作频率的函数。

// 在这个例子中,我们希望访问 yesno.wtf/api 的频率

// AJAX 请求直到用户输入完毕才会发出。想要了解更多关于

// `_.debounce` 函数 (及其近亲 `_.throttle`) 的知识,

// 请参考:https://lodash.com/docs#debounce

getAnswer: _.debounce(

function () {

if (this.question.indexOf('?') === -1) {

this.answer = 'Questions usually contain a question mark. ;-)'

return

}

this.answer = 'Thinking...'

var vm = this

axios.get('https://yesno.wtf/api')

.then(function (response) {

vm.answer = _.capitalize(response.data.answer)

})

.catch(function (error) {

vm.answer = 'Error! Could not reach the API. ' + error

})

},

// 这是我们为判定用户停止输入等待的毫秒数

500

)

}

})

</script> 结果:当没有输入?号,那么显示如下:

当有?时候会输出“yes”或者“no”

具体案例效果地址:侦听器

在这个示例中,使用 watch 选项允许我们执行异步操作 (访问一个 API),我们执行该操作的频率,并在我们得到最终结果前,设置中间状态。这些都是计算属性无法做到的。

相信看了本文案例你已经掌握了方法,更多精彩请关注Gxl网其它相关文章!

推荐阅读:

有哪些js使用方式(附代码)

如何动态引入JS文件

六三科技网还为您提供以下相关内容希望对您有帮助:

Vue.js提升必知的几点总结

这次给大家带来Vue.js提升必知的几点总结,Vue.js提升的注意事项有哪些,下面就是实战案例,一起来看一下。第一招:化繁为简的Watchers场景还原:created(){ this.fetchPostList()},watch: { searchInputValue(){ this.f...

Vue在前端开发中需要注意什么

*/四、谨慎使用 (有潜在危险的模式)1. 没有在 v-if/v-if-else/v-else 中使用 key如果一组 v-if + v-else 的元素类型相同,最好使用 key (比如两个 元素)。正例: 错误:{{ error }} {{ results }}反例: 错误:{{ ...

使用Vue时有哪些小技巧

当一个组件没有声明任何 prop 时,这里会包含所有父作用域的绑定,并且可以通过 v-bind="$attrs" 传入内部组件——在创建更高层次的组件时非常有用。2 注意到子组件的 @focus="$emit('focus', $event)" 其实什么都没做,只是把ev...

Vue.JS的自定义指令应该如何使用

Vue.js 允许你注册自定义指令,实质上是让你教 Vue 一些新技巧:怎样将数据的变化映射到 DOM 的行为。你可以使用Vue.directive(id, definition)的方法传入指令id和定义对象来注册一个全局自定义指令。定义对象需要提供一些...

怎样操作vue进行数据传递

这次给大家带来怎样操作vue进行数据传递,操作vue进行数据传递的注意事项有哪些,下面就是实战案例,一起来看一下。组件(Component)是 Vue.js 最强大的功能。组件可以封装可重用的代码,通过传入对象的不同,实现组件的复用,...

Vue.js中ref ($refs)用法举例总结及应注意的坑

看Vue.js文档中的ref部分,自己总结了下ref的使用方法以便后面查阅。HTML 部分 js部分 HTML部分 JS部分 HTML部分 JS部分 HTML部分 JS部分 1、如果通过v-for 遍历想加不同的ref时记得加 : 号,即 :ref =某变量 ;...

怎么操作Vue加载顺序

这次给大家带来怎么操作Vue加载顺序,操作Vue加载顺序的注意事项有哪些,下面就是实战案例,一起来看一下。在Vuejs 1.0版本中,如果父子组件进行配合,它们的生命周期执行具有如下特点:1. created总是先父后子生命周期函数...

vuejs项目打包后可能会出现的问题有哪些

这次给大家带来vuejs项目打包后可能会出现的问题有哪些,vuejs项目打包的注意事项有哪些,下面就是实战案例,一起来看一下。一:使用CDN资源我们在打包时,会将package.json里,dependencies对象里插件打包起来,我们可以将其中...

如何使用vue注册组件

五、模板的注意事项 1. 以子标签的形式在父组件中使用 &lt;parent-component&gt; &lt;child-component&gt;&lt;/child-component&gt; &lt;/parent-component&gt; 上面是错误的。为什么这种方式无效呢?因为当子组件注册到父组件时,Vue.js会编译好父组件的模板,模...

怎样操作Vue表单类父子组件数据传递

这次给大家带来怎样操作Vue表单类父子组件数据传递,操作Vue表单类父子组件数据传递的注意事项有哪些,下面就是实战案例,一起来看一下。使用Vue.js进行项目开发,那必然会使用基于组件的开发方式,这种方式的确给开发和维护带来的...

Top