vue.js有两种使用语法,选项式api
和组合式api
,选项式api对待新人更加友好,符合面向对象的味道,而组合式api更加的灵活,适合老人进行复杂vue单页面展示等操作。
<script>
export default {
// 组件选项
// 此处声明一些响应式状态
}
</script>
<template>
<h1>Make me dynamic!</h1>
</template>
<script setup>
import { ref } from 'vue'
// 组件逻辑
// 此处声明一些响应式状态
</script>
<template>
<h1>Make me dynamic!</h1>
</template>
1.声明式渲染
Vue 的核心功能是声明式渲染:通过扩展于标准 HTML 的模板语法,我们可以根据 JavaScript 的状态来描述 HTML 应该是什么样子的。当状态改变时,HTML 会自动更新。
能在改变时触发更新的状态被认为是响应式的。在 Vue 中,响应式状态被保存在组件中。
我们可以使用 data 组件选项来声明响应式状态,该选项应该是一个返回对象的函数:
export default {
data() {
return {
message: 'Hello World!'
}
}
}
<template>
{{message}}
</template>
上面的template指的是<div id='app'></div>
,如果我们不使用template,就需要转换写法。
<script type="module">
import { createApp } from 'vue'
createApp({
// 组件选项
// 此处声明一些响应式状态
}).mount('#app')
</script>
<div id="app">
<h1>Make me dynamic!</h1>
</div>
2. attribute绑定
vue为我们提供了属性绑定v-bind
,他可以将属性进行响应式绑定。
<script type="module">
import { createApp } from 'vue'
createApp({
data() {
return {
titleClass: 'title'
}
}
}).mount('#app')
</script>
<div id="app">
<h1 v-bind:class='titleClass'>Make me red</h1> <!-- 此处添加一个动态 class 绑定 -->
</div>
vue还为我们提供了简写方式,:attribute=
<style>
#nh{
color:blue;
}
</style>
<script type="module">
import { createApp } from 'vue'
createApp({
data() {
return {
new_id:'nh'
}
}
}).mount('#app')
</script>
<div id="app">
<h1 id='new_id'>Make me red</h1>
</div>
3. 事件监听
vue封装了事件监听,v-on:method
<script type="module">
import { createApp } from 'vue'
createApp({
data() {
return {
count: 0
}
}
}).mount('#app')
</script>
<div id="app">
<!-- 使此按钮生效 -->
<button v-on:click='count++'>count is: {{ count }}</button>
</div>
你也可以简写@click=
在事件监听的后面需要写方法,而方法写在methods
里面。
<script type="module">
import { createApp } from 'vue'
createApp({
data() {
return {
count: 0
}
},
methods:{
more(){
this.count++
}
}
}).mount('#app')
</script>
<div id="app">
<!-- 使此按钮生效 -->
<button v-on:click='more'>count is: {{ count }}</button>
</div>
4.表单绑定
我们可以通过v-on
、v-bind
来进行双向绑定。
<script type="module">
import { createApp } from 'vue'
createApp({
data() {
return {
text: ''
}
},
methods: {
input_text(e){
this.text=e.target.value;
}
}
}).mount('#app')
</script>
<div id="app">
<input type='text' :value=text @input=input_text>
<P>
{{this.text}}
</P>
</div>
这样就可以让input输入的值和声明对象进行绑定。
vue给我们提供了更加简单的方法 v-model
,他可以直接实现上面的操作集,使得输入和参数进行绑定。
<script type="module">
import { createApp } from 'vue'
createApp({
data() {
return {
text: ''
}
},
methods: {
}
}).mount('#app')
</script>
<div id="app">
<input v-model=text>
<P>
{{this.text}}
</P>
</div>
v-model 不仅支持文本输入框,也支持诸如多选框、单选框、下拉框之类的输入类型。我们在指南 - 表单绑定中讨论了更多的细节。
5.条件渲染
我们可以使用 v-if
指令来有条件地渲染元素:
<script type="module">
import { createApp } from 'vue'
createApp({
data() {
return {
awesome: true
}
},
methods: {
toggle() {
this.awesome=!this.awesome;
}
}
}).mount('#app')
</script>
<div id="app">
<button @click="toggle">toggle</button>
<h1 v-if=awesome>Vue is awesome!</h1>
<h1>Oh no 😢</h1>
</div>
当点击toggle按钮,将参数转换为false,h1就会消失。
我们也可以使用 v-else 和 v-else-if 来表示其他的条件分支:
<script type="module">
import { createApp } from 'vue'
createApp({
data() {
return {
awesome: true
}
},
methods: {
toggle() {
this.awesome = !this.awesome
}
}
}).mount('#app')
</script>
<div id="app">
<button @click="toggle">toggle</button>
<h1 v-if="awesome">Vue is awesome!</h1>
<h1 v-else>Oh no 😢</h1>
</div>
6. 列表渲染
我们可以使用 v-for 指令来渲染一个基于源数组的列表:
<ul>
<li v-for="todo in todos" :key="todo.id">
{{ todo.text }}
</li>
</ul>
注意,我们还给每个 todo 对象设置了唯一的 id,并且将它作为特殊的 key attribute 绑定到每个 li。key 使得 Vue 能够精确的移动每个 li,以匹配对应的对象在数组中的位置。
我们可以通过这个实现一个添加与删除。
<script type="module">
import { createApp } from 'vue'
// 给每个 todo 对象一个唯一的 id
let id = 0
createApp({
data() {
return {
newTodo: '',
todos: [
{ id: id++, text: 'Learn HTML' },
{ id: id++, text: 'Learn JavaScript' },
{ id: id++, text: 'Learn Vue' }
]
}
},
methods: {
addTodo() {
this.todos.push({ id: id++, text: this.newTodo })
this.newTodo = ''
},
removeTodo(todo) {
this.todos = this.todos.filter((t) => t !== todo)
}
}
}).mount('#app')
</script>
<div id="app">
<form @submit.prevent="addTodo">
<input v-model="newTodo">
<button>Add Todo</button>
</form>
<ul>
<li v-for="todo in todos" :key="todo.id">
{{ todo.text }}
<button @click="removeTodo(todo)">X</button>
</li>
</ul>
</div>
7.计算属性
让我们在上一步的 todo 列表基础上继续。现在,我们已经给每一个 todo 添加了切换功能。这是通过给每一个 todo 对象添加 done 属性来实现的,并且使用了 v-model 将其绑定到复选框上:
<li v-for="todo in todos">
<input type="checkbox" v-model="todo.done">
...
</li>
下一个可以添加的改进是隐藏已经完成的 todo。我们已经有了一个能够切换 hideCompleted 状态的按钮。但是应该如何基于状态渲染不同的列表项呢?
介绍一个新概念:计算属性。我们可以使用 computed 选项声明一个响应式的属性,它的值由其他属性计算而来:
computed: {
filteredTodos() {
// 根据 `this.hideCompleted` 返回过滤后的 todo 项目
}
}
计算属性会自动跟踪其计算中所使用的到的其他响应式状态,并将它们收集为自己的依赖。计算结果会被缓存,并只有在其依赖发生改变时才会被自动更新。
<script type="module">
import { createApp } from 'vue'
let id = 0
createApp({
data() {
return {
newTodo: '',
hideCompleted: false,
todos: [
{ id: id++, text: 'Learn HTML', done: true },
{ id: id++, text: 'Learn JavaScript', done: true },
{ id: id++, text: 'Learn Vue', done: false }
]
}
},
computed: {
newTodos(){
return this.hideCompleted?
this.todos.filter((t)=>!t.done):this.todos;
}
},
methods: {
addTodo() {
this.todos.push({ id: id++, text: this.newTodo, done: false })
this.newTodo = ''
},
removeTodo(todo) {
this.todos = this.todos.filter((t) => t !== todo)
}
}
}).mount('#app')
</script>
<div id="app">
<form @submit.prevent="addTodo">
<input v-model="newTodo">
<button>Add Todo</button>
</form>
<ul>
<li v-for="todo in newTodos" :key="todo.id">
<input type="checkbox" v-model="todo.done">
<span :class="{ done: todo.done }">{{ todo.text }}</span>
<button @click="removeTodo(todo)">X</button>
</li>
</ul>
<button @click="hideCompleted = !hideCompleted">
{{ hideCompleted ? 'Show all' : 'Hide completed' }}
</button>
</div>
8.生命周期和模板引用
目前为止,Vue 为我们处理了所有的 DOM 更新,这要归功于响应性和声明式渲染。然而,有时我们也会不可避免地需要手动操作 DOM。
这时我们需要使用模板引用——也就是指向模板中一个 DOM 元素的 ref。我们需要通过这个特殊的 ref attribute 来实现模板引用:
<div ref='divAttributeRef'></div>
经过这个后,div就和ref
属性合并。然后可以在钩子函数mounted
中进行ref内容的更改。
<script>
createApp({
mounted(){
this.$refs.divAttributeRef.textContent='cmc';
}
})
</script>
<div ref='divAttributeRef'>
hello
</div>
8.1 生命周期
vue为我们提供了生命周期钩子,允许在vue渲染模板的不同程度进行操作。
分别是``
具体可以看官网文档。
9.监听器
有时候,我们需要监视某个元素的动作进行一系列的操作,这个时候就需要监听器watch
的帮助了。
<script>
createApp({
data(){
return{
todo:{},
todoId:1,
}
},
methods:{
async fetchData() {
this.todoData = null
const res = await fetch(
`https://jsonplaceholder.typicode.com/todos/${this.todoId}`
)
this.todoData = await res.json()
}
},
watch:{
todoId(newId){
this.fetchData();
},
},
}).mount("#app");
</script>
<div id="app">
<p>Todo id: {{ todoId }}</p>
<button @click="todoId++">Fetch next todo</button>
<p v-if="!todoData">Loading...</p>
<pre v-else>{{ todoData }}</pre>
</div>
10. 组件
之前的操作我们使用的都是单组件,而vue应用往往是由嵌套组件形成的。父组件可以渲染另一个子组件,要想使用,首先需要引用。
`import ChildComp from './ChildComp.js'
createApp({
components: {
ChildComp
}
})
在components
中注册之后,我们需要将他放入到我们的dom
中,使用html的语法结构放入即可。
<script type="module">
import { createApp } from 'vue'
import childcomp from './ChildComp.js'
createApp({
// register child component
components:{
childcomp,
}
}).mount('#app')
</script>
<div id="app">
<!-- render child component -->
<childcomp></childcomp>
</div>
11.props
子组件怎么得到父组件的数据呢,vue为我们提供了props
,可以动态的接收数据。
请注意,子组件这里写的是参数的类型,而父组件那里才是具体数值
export default{
props: {
msg:String,
},
template: `
<h2>{{ msg || 'No props passed yet' }}</h2>
`
}
父组件:
import com from './com.js'
export default{
components:{
com,
},
data(){
return{
greeting:'你好,bro',
}
},
}
<template>
<com msg='sdfsdf'></com>
</template>
如果你想用传递动态参数,你可以使用v-bind
进行绑定。
<com :msg=greeting></com>
12. emits
除了传递参数,子组件还可以给予父组件触发事件:
子组件:
export default {
// 声明触发的事件
emits: ['response'],
created() {
// 带参数触发
this.$emit('response', 'hello from child')
}
}
this.$emit()
的第一个参数是事件的名称。其他所有参数都将传递给事件监听器。
父组件可以使用 v-on
监听子组件触发的事件——这里的处理函数接收了子组件触发事件时的额外参数并将它赋值给了本地状态:
<child-comp @response="(msg) => childMsg = msg"></child-comp>
13 插槽
我们可以利用插槽solt
来为子组件覆默认值。
export default {
template: `
<slot>Fallback content</slot>
`
}
如果我们没有在组件中放内容,那就会将solt的内容放到上面。
<div id="app">
<child-comp>Message: {{ msg }}</child-comp>
</div>
这些就是基础的vue框架使用,具体的内容你可以观看官网文档。