您现在的位置是:网站首页> 小程序设计

基本工具

摘要

npm为node的包管理工具,安装上node.js就有了npm

除了数据 property,Vue 实例还暴露了一些有用的实例 property 与方法。它们都有前缀 $,以便与用户定义的 property 区分开来。例如:


var data = { a: 1 }

var vm = new Vue({

  el: '#example',

  data: data

})


vm.$data === data // => true

vm.$el === document.getElementById('example') // => true


// $watch 是一个实例方法

vm.$watch('a', function (newValue, oldValue) {

  // 这个回调将在 `vm.a` 改变后调用

})

以后你可以在 API 参考中查阅到完整的实例 property 和方法的列表

计算属性

<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"

计算属性是基于它们的响应式依赖进行缓存的。只在相关响应式依赖发生改变时它们才会重新求值。这就意味着只要 message 还没有发生改变,多次访问 reversedMessage 计算属性会立即返回之前的计算结果,而不必再次执行函数。


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


computed: {

  now: function () {

    return Date.now()

  }

}

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


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

计算属性 vs 侦听属性

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


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

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 选项提供了一个更通用的方法,来响应数据的变化。当需要在数据变化时执行异步或开销较大的操作时,这个方式是最有用的。


例如:


<div id="watch-example">

  <p>

    Ask a yes/no question:

    <input v-model="question">

  </p>

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

</div>

<!-- 因为 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.debouncedGetAnswer()

    }

  },

  created: function () {

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

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

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

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

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

    this.debouncedGetAnswer = _.debounce(this.getAnswer, 500)

  },

  methods: {

    getAnswer: 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

        })

    }

  }

})

</script>

结果:


Ask a yes/no question: 


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


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


除了 watch 选项之外,您还可以使用命令式的 vm.$watch API。

绑定 HTML Class

观看本节视频讲解

对象语法

我们可以传给 v-bind:class 一个对象,以动态地切换 class:


<div v-bind:class="{ active: isActive }"></div>

上面的语法表示 active 这个 class 存在与否将取决于数据 property isActive 的 truthiness


你可以在对象中传入更多字段来动态切换多个 class。此外,v-bind:class 指令也可以与普通的 class attribute 共存。当有如下模板:


<div

  class="static"

  v-bind:class="{ active: isActive, 'text-danger': hasError }"

></div>

和如下 data:


data: {

  isActive: true,

  hasError: false

}

结果渲染为:


<div class="static active"></div>

当 isActive 或者 hasError 变化时,class 列表将相应地更新。例如,如果 hasError 的值为 true,class 列表将变为 "static active text-danger"。


绑定的数据对象不必内联定义在模板里:


<div v-bind:class="classObject"></div>

data: {

  classObject: {

    active: true,

    'text-danger': false

  }

}

渲染的结果和上面一样。我们也可以在这里绑定一个返回对象的计算属性。这是一个常用且强大的模式:


<div v-bind:class="classObject"></div>

data: {

  isActive: true,

  error: null

},

computed: {

  classObject: function () {

    return {

      active: this.isActive && !this.error,

      'text-danger': this.error && this.error.type === 'fatal'

    }

  }

}

数组语法

我们可以把一个数组传给 v-bind:class,以应用一个 class 列表:


<div v-bind:class="[activeClass, errorClass]"></div>

data: {

  activeClass: 'active',

  errorClass: 'text-danger'

}

渲染为:


<div class="active text-danger"></div>

如果你也想根据条件切换列表中的 class,可以用三元表达式:


<div v-bind:class="[isActive ? activeClass : '', errorClass]"></div>

这样写将始终添加 errorClass,但是只有在 isActive 是 truthy[1] 时才添加 activeClass。


不过,当有多个条件 class 时这样写有些繁琐。所以在数组语法中也可以使用对象语法:

<div v-bind:class="[{ active: isActive }, errorClass]"></div>

用在组件上

这个章节假设你已经对 Vue 组件有一定的了解。当然你也可以先跳过这里,稍后再回过头来看。


当在一个自定义组件上使用 class property 时,这些 class 将被添加到该组件的根元素上面。这个元素上已经存在的 class 不会被覆盖。


例如,如果你声明了这个组件:


Vue.component('my-component', {

  template: '<p class="foo bar">Hi</p>'

})

然后在使用它的时候添加一些 class:


<my-component class="baz boo"></my-component>

HTML 将被渲染为:


<p class="foo bar baz boo">Hi</p>

对于带数据绑定 class 也同样适用:


<my-component v-bind:class="{ active: isActive }"></my-component>

当 isActive 为 truthy[1] 时,HTML 将被渲染成为:


<p class="foo bar active">Hi</p>

绑定内联样式

对象语法

v-bind:style 的对象语法十分直观——看着非常像 CSS,但其实是一个 JavaScript 对象。CSS property 名可以用驼峰式 (camelCase) 或短横线分隔 (kebab-case,记得用引号括起来) 来命名:


<div v-bind:style="{ color: activeColor, fontSize: fontSize + 'px' }"></div>

data: {

  activeColor: 'red',

  fontSize: 30

}

直接绑定到一个样式对象通常更好,这会让模板更清晰:


<div v-bind:style="styleObject"></div>

data: {

  styleObject: {

    color: 'red',

    fontSize: '13px'

  }

}

同样的,对象语法常常结合返回对象的计算属性使用。


数组语法

v-bind:style 的数组语法可以将多个样式对象应用到同一个元素上:


<div v-bind:style="[baseStyles, overridingStyles]"></div>

自动添加前缀

当 v-bind:style 使用需要添加浏览器引擎前缀的 CSS property 时,如 transform,Vue.js 会自动侦测并添加相应的前缀。


多重值

2.3.0+


从 2.3.0 起你可以为 style 绑定中的 property 提供一个包含多个值的数组,常用于提供多个带前缀的值,例如:


<div :style="{ display: ['-webkit-box', '-ms-flexbox', 'flex'] }"></div>

这样写只会渲染数组中最后一个被浏览器支持的值。在本例中,如果浏览器支持不带浏览器前缀的 flexbox,那么就只会渲染 display: flex。





上一篇:uniapp编译相关

下一篇:vue 标签语法

Top