Skip to content
On this page

Vue.js 基础语法

Vue.js 提供了一套简洁的模板语法,让开发者能够以声明式的方式将数据渲染到DOM中。

模板语法

插值

Vue.js 使用 双大括号语法进行文本插值:

vue
<template>
  <div>
    <!-- 文本插值 -->
    <p>{{ message }}</p>
    
    <!-- 使用JavaScript表达式 -->
    <p>{{ message + '!' }}</p>
    <p>{{ count > 10 ? '大于10' : '小于等于10' }}</p>
    <p>{{ user.firstName + ' ' + user.lastName }}</p>
  </div>
</template>

<script>
export default {
  data() {
    return {
      message: 'Hello Vue!',
      count: 5,
      user: {
        firstName: 'John',
        lastName: 'Doe'
      }
    }
  }
}
</script>

指令

指令是带有 v- 前缀的特殊属性,用于在表达式的值改变时响应式地作用于DOM:

vue
<template>
  <div>
    <!-- v-text: 更新元素的文本内容 -->
    <p v-text="message"></p>
    
    <!-- v-html: 更新元素的innerHTML -->
    <div v-html="rawHtml"></div>
    
    <!-- v-show: 条件显示 -->
    <p v-show="isVisible">这是一段条件显示的文本</p>
    
    <!-- v-if/v-else/v-else-if: 条件渲染 -->
    <div v-if="type === 'A'">A</div>
    <div v-else-if="type === 'B'">B</div>
    <div v-else>C</div>
    
    <!-- v-for: 列表渲染 -->
    <ul>
      <li v-for="item in items" :key="item.id">
        {{ item.name }}
      </li>
    </ul>
    
    <!-- v-bind: 动态绑定属性 -->
    <img v-bind:src="imageSrc" :alt="imageAlt">
    <button :disabled="isDisabled">按钮</button>
    
    <!-- v-on: 事件监听 -->
    <button v-on:click="handleClick">点击</button>
    <button @click="handleClick">点击</button> <!-- @ 是 v-on: 的缩写 -->
    
    <!-- v-model: 双向数据绑定 -->
    <input v-model="inputValue">
    <textarea v-model="textareaValue"></textarea>
  </div>
</template>

<script>
export default {
  data() {
    return {
      message: 'Hello Vue!',
      rawHtml: '<span style="color: red">红色文本</span>',
      isVisible: true,
      type: 'A',
      items: [
        { id: 1, name: '苹果' },
        { id: 2, name: '香蕉' },
        { id: 3, name: '橙子' }
      ],
      imageSrc: '/path/to/image.jpg',
      imageAlt: '图片描述',
      isDisabled: false,
      inputValue: '',
      textareaValue: ''
    }
  },
  methods: {
    handleClick() {
      console.log('按钮被点击了!');
    }
  }
}
</script>

计算属性和侦听器

计算属性

计算属性是基于响应式依赖进行缓存的,只有依赖发生改变时才会重新计算:

vue
<template>
  <div>
    <p>原始消息: {{ message }}</p>
    <p>反转消息: {{ reversedMessage }}</p>
    <p>反转消息(方法): {{ reverseMessage() }}</p>
  </div>
</template>

<script>
export default {
  data() {
    return {
      message: 'Hello Vue!'
    }
  },
  computed: {
    // 计算属性
    reversedMessage() {
      return this.message.split('').reverse().join('')
    }
  },
  methods: {
    // 方法(每次渲染都会执行)
    reverseMessage() {
      return this.message.split('').reverse().join('')
    }
  }
}
</script>

侦听器

当需要在数据变化时执行异步或开销较大的操作时,侦听器很有用:

vue
<template>
  <div>
    <p>问一个问题是(Yes/No):</p>
    <p>{{ question }}</p>
    <input v-model="question" @input="debouncedGetAnswer">
  </div>
</template>

<script>
import _ from 'lodash'

export default {
  data() {
    return {
      question: '',
      answer: '问题以 ? 结尾时我会给你答案'
    }
  },
  watch: {
    // 侦听 question 的变化
    question(newQuestion, oldQuestion) {
      this.answer = '正在思考...'
      this.getAnswer()
    }
  },
  created() {
    // 使用lodash的防抖功能
    this.debouncedGetAnswer = _.debounce(this.getAnswer, 500)
  },
  methods: {
    async getAnswer() {
      if (this.question.indexOf('?') === -1) {
        this.answer = '问题以 ? 结尾时我会给你答案'
        return
      }
      
      this.answer = '正在思考...'
      try {
        const res = await fetch('https://yesno.wtf/api')
        this.answer = (await res.json()).answer
      } catch (error) {
        this.answer = '无法获取答案,请稍后重试'
      }
    }
  }
}
</script>

条件渲染

v-if vs v-show

vue
<template>
  <div>
    <!-- v-if: 条件渲染,完全销毁/创建DOM元素 -->
    <h1 v-if="awesome">Vue很awesome!</h1>
    
    <!-- v-show: 条件显示,通过CSS切换显示/隐藏 -->
    <h1 v-show="awesome">Vue很awesome!</h1>
    
    <!-- v-if, v-else-if, v-else -->
    <div v-if="type === 'A'">
      A
    </div>
    <div v-else-if="type === 'B'">
      B
    </div>
    <div v-else>
      Not A/B
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      awesome: true,
      type: 'A'
    }
  }
}
</script>

列表渲染

v-for 基础用法

vue
<template>
  <div>
    <!-- 遍历数组 -->
    <ul>
      <li v-for="item in items" :key="item.id">
        {{ item.name }} - {{ item.price }}
      </li>
    </ul>
    
    <!-- 使用索引 -->
    <ul>
      <li v-for="(item, index) in items" :key="item.id">
        {{ index }} - {{ item.name }}
      </li>
    </ul>
    
    <!-- 遍历对象 -->
    <ul>
      <li v-for="(value, key) in object" :key="key">
        {{ key }}: {{ value }}
      </li>
    </ul>
    
    <!-- 遍历数字 -->
    <span v-for="n in 10" :key="n">{{ n }} </span>
  </div>
</template>

<script>
export default {
  data() {
    return {
      items: [
        { id: 1, name: '苹果', price: 5 },
        { id: 2, name: '香蕉', price: 3 },
        { id: 3, name: '橙子', price: 4 }
      ],
      object: {
        name: 'John',
        age: 30,
        city: 'New York'
      }
    }
  }
}
</script>

事件处理

事件修饰符

vue
<template>
  <div>
    <!-- 普通事件 -->
    <button @click="counter++">计数器: {{ counter }}</button>
    
    <!-- 事件修饰符 -->
    <!-- .stop - 阻止事件冒泡 -->
    <div @click="outerClick">
      外层
      <button @click.stop="innerClick">内层 - 不会冒泡</button>
    </div>
    
    <!-- .prevent - 阻止默认行为 -->
    <form @submit.prevent="onSubmit">
      <input type="text" v-model="inputValue">
      <button type="submit">提交</button>
    </form>
    
    <!-- .capture - 使用事件捕获模式 -->
    <div @click.capture="captureClick">
      捕获模式
      <button @click="normalClick">普通点击</button>
    </div>
    
    <!-- .self - 只在事件目标是元素本身时触发 -->
    <div @click.self="selfClick">
      只在点击自身时触发
      <button @click="buttonClick">按钮</button>
    </div>
    
    <!-- .once - 事件只触发一次 -->
    <button @click.once="onceClick">只触发一次</button>
    
    <!-- 按键修饰符 -->
    <input @keyup.enter="onEnter" @keyup.esc="onEscape">
    
    <!-- 系统修饰键 -->
    <div @click.ctrl="ctrlClick">按住Ctrl点击</div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      counter: 0,
      inputValue: ''
    }
  },
  methods: {
    outerClick() {
      console.log('外层点击')
    },
    innerClick() {
      console.log('内层点击')
    },
    onSubmit() {
      console.log('表单提交被阻止')
    },
    captureClick() {
      console.log('捕获阶段触发')
    },
    normalClick() {
      console.log('普通点击')
    },
    selfClick() {
      console.log('只在点击自身时触发')
    },
    buttonClick() {
      console.log('按钮点击')
    },
    onceClick() {
      console.log('只触发一次')
    },
    onEnter() {
      console.log('按下了Enter键')
    },
    onEscape() {
      console.log('按下了Escape键')
    },
    ctrlClick() {
      console.log('按住Ctrl点击')
    }
  }
}
</script>

表单输入绑定

v-model 基础用法

vue
<template>
  <div>
    <!-- 文本输入 -->
    <input v-model="message" placeholder="输入一些文字">
    <p>消息: {{ message }}</p>
    
    <!-- 多行文本 -->
    <textarea v-model="textareaValue" placeholder="多行文本"></textarea>
    <p>多行文本: {{ textareaValue }}</p>
    
    <!-- 复选框 -->
    <input type="checkbox" id="checkbox" v-model="checked">
    <label for="checkbox">{{ checked ? '已选中' : '未选中' }}</label>
    
    <!-- 多个复选框 -->
    <div>
      <input type="checkbox" id="jack" value="Jack" v-model="checkedNames">
      <label for="jack">Jack</label>
      <input type="checkbox" id="john" value="John" v-model="checkedNames">
      <label for="john">John</label>
      <input type="checkbox" id="mike" value="Mike" v-model="checkedNames">
      <label for="mike">Mike</label>
      <br>
      <span>选中: {{ checkedNames }}</span>
    </div>
    
    <!-- 单选按钮 -->
    <div>
      <input type="radio" id="one" value="One" v-model="picked">
      <label for="one">One</label>
      <input type="radio" id="two" value="Two" v-model="picked">
      <label for="two">Two</label>
      <br>
      <span>选中: {{ picked }}</span>
    </div>
    
    <!-- 选择框 -->
    <select v-model="selected">
      <option disabled value="">请选择</option>
      <option>A</option>
      <option>B</option>
      <option>C</option>
    </select>
    <span>选中: {{ selected }}</span>
    
    <!-- 多选选择框 -->
    <select v-model="multiSelected" multiple>
      <option>A</option>
      <option>B</option>
      <option>C</option>
    </select>
    <span>选中: {{ multiSelected }}</span>
  </div>
</template>

<script>
export default {
  data() {
    return {
      message: '',
      textareaValue: '',
      checked: false,
      checkedNames: [],
      picked: '',
      selected: '',
      multiSelected: []
    }
  }
}
</script>

组件基础

组件注册和使用

vue
<!-- MyButton.vue -->
<template>
  <button class="my-button" @click="handleClick">
    <slot></slot>
  </button>
</template>

<script>
export default {
  name: 'MyButton',
  methods: {
    handleClick() {
      this.$emit('click')
    }
  }
}
</script>

<style scoped>
.my-button {
  padding: 8px 16px;
  background-color: #007bff;
  color: white;
  border: none;
  border-radius: 4px;
  cursor: pointer;
}
</style>
vue
<!-- 父组件 -->
<template>
  <div>
    <MyButton @click="onButtonClick">点击我</MyButton>
  </div>
</template>

<script>
import MyButton from './MyButton.vue'

export default {
  components: {
    MyButton
  },
  methods: {
    onButtonClick() {
      console.log('按钮被点击了!')
    }
  }
}
</script>

Vue.js的语法简洁而强大,通过这些基础语法,开发者可以构建出功能丰富的交互式界面。