vue基础

一、简介

1.定义:是一款用于构建用户界面的js框架,基于标准html、css和js构建,提供了一套声明式的、组件化的编程模型,可以高效地开发用户界面。

2.核心功能:

声明式渲染,基于标准html拓展了一套模版语法,使得可以声明式地描述最终输出的html和js状态之间的关系。

响应性:vue会自动跟踪js状态,并在其发生变化时响应式地更新DOM。

3.渐进式框架:vue的设计注重灵活性和“可以被逐步集成”这个特点。

4.单文件组件(标志性功能):用类似于html格式的文件来书写vue组件,被称为单文件组件(也被称为*.vue文件),即vue的单文件组件会将一个组件的逻辑(js),模版(html)和样式(css)封装在同一个文件里。

<script setup>
import { ref } from 'vue'
const count = ref(0)
</script>

<template>
  <button @click="count++">Count is: {{ count }}</button>
</template>

<style scoped>
button {
  font-weight: bold;
}
</style>

5.API风格:选项式API和组合式API

使用选项式API,可以用包含多个选项的对象来描述组件的逻辑,例如data、methods和mounted。选项所定义的属性都会暴露在函数内部的this上,它会指向当前的组件实例。

<script>
export default {
  // data() 返回的属性将会成为响应式的状态
  // 并且暴露在 `this` 上
  data() {
    return {
      count: 0
    }
  },

  // methods 是一些用来更改状态与触发更新的函数
  // 它们可以在模板中作为事件处理器绑定
  methods: {
    increment() {
      this.count++
    }
  },

  // 生命周期钩子会在组件生命周期的各个不同阶段被调用
  // 例如这个函数就会在组件挂载完成后被调用
  mounted() {
    console.log(`The initial count is ${this.count}.`)
  }
}
</script>

<template>
  <button @click="increment">Count is: {{ count }}</button>
</template>

通过组合式API,可以使用导入的API函数来描述组件逻辑。在单文件组件中,组合式API通常会与

<script setup>
import { ref, onMounted } from 'vue'

// 响应式状态
const count = ref(0)

// 用来修改状态、触发更新的函数
function increment() {
  count.value++
}

// 生命周期钩子
onMounted(() => {
  console.log(`The initial count is ${count.value}.`)
})
</script>

<template>
  <button @click="increment">Count is: {{ count }}</button>
</template>

二、创建一个应用

1.每个vue应用都是通过createApp函数创建一个新的应用实例。传入的对象是一个组件,每一个应用都需要一个“根组件”,其他组件作为其子组件。使用单文件组件,可以直接从另一个文件中导入根组件。

大多数应用基本是一颗嵌套的、可重用的组件树组成的。

//普通
import { createApp } from 'vue'

const app = createApp({
  /* 根组件选项 */
})
//单文件组件
import { createApp } from 'vue'
// 从一个单文件组件中导入根组件
import App from './App.vue'
const app = createApp(App)

2.app实例必须调用.mount()方法后才会渲染出来。该方法接收一个“容器”参数,可以是一个实际的DOM元素或者是一个css选择器字符串

//html
<div id="app">
  <button @click="count++">{{ count }}</button>
</div>
//js
import { createApp } from 'vue'

const app = createApp({
  data() {
    return {
      count: 0
    }
  }
})

app.mount('#app')

app根组件的内容将会被渲染在容器元素里面。容器元素自己将不会被视为应用的一部分。

.mount() 方法应该始终在整个app配置和资源注册完成后被调用。同时请注意,不同于其他资源注册方法,它的返回值是根组件实例而非app实例。

根组件的模版template通常是组件本身的一部分,但也可以通过在挂载容器内编写template来单独提供。

如果根组件没有设置template选项时,会自动使用容器的innerHTML作为模版。DOM内模版通常用于无构建步骤的vue应用程序。

3.应用配置

app实例会暴露一个.config对象,允许来配置一些高级应用级的选项,如定义app级的错误处理器,用来捕获所有子组件上的错误、注册app内可用的资源(组件等)

4.多个app实例

允许创建多个vue app,拥有自己的用于配制和全局资源的作用域。

三、template语法

使用基于html的template语法,能够声明式地将组件实例的数据绑定到呈现的DOM上。底层机制中,vue会将template编译成高度优化到js代码,当app状态变化时,能够推导出需要重新渲染的组件的最少的数量,使用最少的dom操作。模版语法主要分为插值语法和指令语法。

1.插值语法

使用双大括号{{xxx}},括号中的内容会被替换成相应组件实例中对应属性的值,一旦该属性发生变化,模版中用到该数据的地方也会自动更新。

也支持绑定js表达式,调用函数

<span>Message: {{ msg }}</span>

{{ number + 1 }}

{{ ok ? 'YES' : 'NO' }}

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

<div :id="`list-${id}`"></div>

2.指令语法

“v-”作为前缀,表明是有vue提供的特殊attribute,指令的作用是在其表达式的值变化时响应式地更新dom

v-html:绑定html

v-bind:

绑定bool值的时候,根据true / false 值来决定 attribute 是否应该存在于该元素上,当attribute为真值或一个空字符串,则会包含这个attribute,否则被忽略

可以通过对象,将包含多个attribute的js对象绑定到单个元素上

v-if:基于表达式的值的真假来移除/插入元素v-on:监听DOM事件,缩写@

指令参数可以使用js表达式,包含在方括号内

//v-html绑定html
<p>Using v-html directive: <span v-html="rawHtml"></span></p>
//绑定一个attribute
<div v-bind:id="dynamicId"></div>//元素的id attribute与组件的dynamicId属性保持一致
<div :id="dynamicId"></div>//v-bind简写

四、响应式状态state和方法methods

1.用 data 选项来声明组件的响应式状态。

此选项的值应为返回一个对象的函数。Vue 将在创建新组件实例的时候调用此函数,并将函数返回的对象用响应式系统进行包装。此对象的所有顶层属性都会被代理到组件实例 (即方法和生命周期钩子中的 this) 上。不在data上定义,直接向组件添加新属性,无法出发响应式更新。

export default {
  data() {
    return {
      count: 1
    }
  },

  // `mounted` 是生命周期钩子
  mounted() {
    // `this` 指向当前组件实例
    console.log(this.count) // => 1

    // 数据属性也可以被更改
    this.count = 2
  }
}

2.通过methods向组件添加方法,methods是一个包含所有对象的方法。

vue自动为methods中的方法绑定指向组件实例的this,不能在定义method是时使用箭头函数。

当改变嵌套对象或者数组时,变化也是可以被检测到的。

修改了响应式state时,dom会自动更新,但不是同步的,会在nexttick更新周期中缓冲所有状态的修改,确保不管进行了多少次状态的修改,每个组件都只被更新一次。

对于有状态的方法,多个复用的组件会共享state,可以在created生命周期hook中创建该方法,每个实例就可以有自己的state。

五、计算属性

基于响应式state,进行一些操作和计算得到的属性。例如 full name=first name+last name,first name和last name是响应式属性,full name是计算属性。

也可以通过函数来获得这个计算结果,但计算属性值仅会在其依赖的响应式属性更新的时候才重新计算。而函数方法调用总是会在重新渲染发生时再次执行。

计算属性默认是只读的,如果要修改的话,需要同时提供getter和setter。

计算属性的getter不应该具有副作用,不要进行异步请求或者更改dom,仅是描述如何根据其他值派生一个值。

应该避免更新计算属性值。

六、class和style绑定

class

class放在html标签中,其属性值是样式规则中类选择器名(样式类名)的集合,样式类名之间用空格分隔。

:class是为class提供的功能增强的用法,使得class的值除了是字符串以为,也可以是对象或数组。

可以通过给:class传递对象来动态切换class

//state
data(){
	return {
  	isActive:true,
    hasError:false
  }
}
//template
<div
  class="static"
  :class="{ active: isActive, 'text-danger': hasError }"//可以直接写成绑定一个对象
></div>
//结果
<div class="static active"></div>

对于只有一个根元素的组件,当使用了 class attribute 时,这些 class 会被添加到根元素上并与该元素上已有的 class 合并。

若有多个根元素组件,可以通过组件的$attrs来指定根元素。

  1. style

:style绑定js对象,对应html元素的style属性。支持驼峰命名,也支持kebab-cased命名。

支持绑定包含多个样式对象的数组,会被合并渲染。

七、条件渲染

1.v-if

条件性渲染一块内容,当指令表达式返回真值时才渲染

2.v-else

为v-if添加一个else块,必须跟在v-if或者v-else-if后面

3.v-else-if

提供v-if的else-if块,可以连续多次重复使用,必须紧跟在一个 v-if 或一个 v-else-if 元素后面

  1. 在template上使用

当要切换多个元素,可以在 元素上使用 v-if,v-else和v-else-if

5.v-show

和v-if用法基本一样,但会在dom渲染中保留该元素,仅切换了该元素上名为display的css属性,不支持在 上使用,不能和v-else搭配使用

v-if 有更高的切换开销,而 v-show 有更高的初始渲染开销。如果需要频繁切换,使用 v-show ;如果在运行时绑定条件很少改变,使用 v-if 。

6.v-if和v-for

当 v-if 和 v-for 同时存在于一个元素上的时候,v-if 会首先被执行。

可以在v-if上包装一层template,再在其上使用v-for

八、列表渲染

1.v-for

使用"item in items"的语法,items是源数据的数组,item是迭代项的别名

支持访问父作用域内的属性和变量,支持使用可选的第二个参数表示当前项的位置索引

可以使用of替代in

//js
data() {
  return {
    parentMessage: 'Parent',
    items: [{ message: 'Foo' }, { message: 'Bar' }]
  }
}
//template
<li v-for="(item, index) in items">
  {{ parentMessage }} - {{ index }} - {{ item.message }}
</li>

2.v-for和对象

可以遍历对象的所有属性,顺序基于对象调用Object.keys()的返回值来决定

3.使用范围值

n in 10,从1开始

4.template

可以在template中使用。

5.通过key管理state

默认情况下,数据项的顺序改变时,vue不会随之移动dom元素的顺序,就地更新,只适用于渲染结果不依赖子组件state或者临时dom状态。

推荐为每个元素对应的块提供唯一的key属性,最好是字符串或者number。

6.数组变化

会修改数组的方法:

push,pop,shift,unshift,splic,sort,reverse

不修改数组,返回新数组的方法:

filter,concat,slice

7.希望显示数组经过过滤或者排序后的内容,而不实际变更或重置原始数据,可以通过计算属性来返回,当使用可变的方法时,需要先创建原数组的副本

九、事件处理

1.监听事件

使用v-on指令,简写@来监听dom事件,并在事件触发时执行对应的js,用法:v-on:click=“handler” @click=“handler”

事件处理器(handler)的值可以是:

2.内联事件处理器:事件被触发时执行的内联js语句(类似于onclick),@click=“count++”," "中是js语句,支持调用方法,“func(x)”,支持传入$event变量,来访问原生DOM事件

3.方法事件处理器:一个指向组件上定义的方法的属性名或者是路径," "中是函数名称

//js
data() {
  return {
    name: 'Vue.js'
  }
},
methods: {
  greet(event) {
    // 方法中的 `this` 指向当前活跃的组件实例
    alert(`Hello ${this.name}!`)
    // `event` 是 DOM 原生事件
    if (event) {
      alert(event.target.tagName)
    }
  }
}
//template
<!-- `greet` 是上面定义过的方法名 -->
<button @click="greet">Greet</button>

4.事件修饰符

event.preventDefault()方法是用于取消事件的默认行为

event.stopPropagation()阻止捕获和冒泡阶段中当前事件的进一步传播

使用事件修饰符可以更专注于数据逻辑而不是dom细节

修饰符:.表示的指令后缀

.stop :停止事件传递

.prevent:阻止事件的默认行为

.self:只当在 event.target 是当前元素自身时触发处理函数

.capture:使事件触发从包含这个元素的顶层开始往下触发

.once:绑定了事件以后只能触发一次,第二次就不会触发

.passive:不想阻止事件的默认行为

<!-- 单击事件将停止传递 -->
<a @click.stop="doThis"></a>

<!-- 提交事件将不再重新加载页面 -->
<form @submit.prevent="onSubmit"></form>

<!-- 修饰语可以使用链式书写 -->
<a @click.stop.prevent="doThat"></a>

<!-- 也可以只有修饰符 -->
<form @submit.prevent></form>

<!-- 仅当 event.target 是元素本身时才会触发事件处理器 -->
<!-- 例如:事件处理器不来自子元素 -->
<div @click.self="doThat">...</div>

<!-- 添加事件监听器时,使用 `capture` 捕获模式 -->
<!-- 例如:指向内部元素的事件,在被内部元素处理前,先被外部处理 -->
<div @click.capture="doThis">...</div>

<!-- 点击事件最多被触发一次 -->
<a @click.once="doThis"></a>

<!-- 滚动事件的默认行为 (scrolling) 将立即发生而非等待 `onScroll` 完成 -->
<!-- 以防其中包含 `event.preventDefault()` -->
<div @scroll.passive="onScroll">...</div>

5.按键修饰符

系统按键修饰符与keyop事件一起使用时,该按键必须在事件发出时处于按下状态

.exact 修饰符允许控制触发一个事件所需的确定组合的系统按键修饰符。

6.鼠标按键修饰符

将处理程序限定为由特定鼠标按键触发的事

十、表单输入绑定

1.基本用法

v-model会根据所使用的元素自动适用对应的DOM属性和事件结合:

文本类型的 和 元素会绑定 value property 并侦听 input 事件;

和 会绑定 checked property 并侦听 change 事件;

会绑定 value property 并侦听 change 事件

v-model会忽略任何表单元素上初始的 value、checked 或 selected attribute,所以应该在 JavaScript 中data部分声明该初始值。

文本:对于需要使用ime的语言,在拼字输入的阶段不会触发更新

选择器:如果v-model表达式的初始值不匹配任何一个选择项,select元素会渲染成一个未选择的状态,在ios上会导致无法选择第一项

//文本
<p>Message is: {{ message }}</p>
<input v-model="message" placeholder="edit me" />
//多行文本
<span>Multiline message is:</span>
<p style="white-space: pre-line;">{{ message }}</p>
<textarea v-model="message" placeholder="add multiple lines"></textarea>
//复选框 单选
<input type="checkbox" id="checkbox" v-model="checked" />
<label for="checkbox">{{ checked }}</label>
//多选绑定同一个数组或者集合
export default {
  data() {
    return {
      checkedNames: []
    }
  }
}
<div>Checked names: {{ checkedNames }}</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>
//单选按钮
<div>Picked: {{ picked }}</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>
//多选
<div>Selected: {{ selected }}</div>
<select v-model="selected" multiple>
  <option>A</option>
  <option>B</option>
  <option>C</option>
</select>

2.值绑定

通过在选项中使用v-bind,可以将v-modal的值绑定到组件实例上的动态数据上

<!-- `picked` 在被选择时是字符串 "a" -->
<input type="radio" v-model="picked" value="a" />

<!-- `toggle` 只会为 truefalse -->
<input type="checkbox" v-model="toggle" />

<!-- `selected` 在第一项被选中时为字符串 "abc" -->
<select v-model="selected">
  <option value="abc">ABC</option>
</select>

3.修饰符

.lazy

.number

.trim

十一、生命周期

每个 Vue 组件实例在创建时都需要经历一系列的初始化步骤,比如设置好数据侦听,编译模板,挂载实例到 DOM,以及在数据改变时更新 DOM。在此期间,会运行生命周期hooks的函数。

十二、侦听器

1.基本示例

使用watch选项在每次响应式属性发生变化的时候触发一个函数

2.深层侦听器

watch默认是浅层的,被侦听的属性只在被赋新值的时候触发回调函数,嵌套的属性发生变化不会触发,需要使用深层侦听器

export default {
  watch: {
    someObject: {
      handler(newValue, oldValue) {
        // 注意:在嵌套的变更中,
        // 只要没有替换对象本身,
        // 那么这里的 `newValue` 和 `oldValue` 相同
      },
      deep: true
    }
  }
}

3.即时回调的侦听器

watch是懒执行,通过handler和immediate:true,可以在组件实例创建时立即调用侦听器

export default {
  // ...
  watch: {
    question: {
      handler(newQuestion) {
        // 在组件实例创建时会立即调用
      },
      // 强制立即执行回调
      immediate: true
    }
  }
  // ...
}

4.回调的触发时机

回调会在vue组件更新之前被调用,在侦听器回调中访问的dom是更新前的状态

通过flush:'post’可以在回调中访问被更新后的dom

export default {
  // ...
  watch: {
    key: {
      handler() {},
      flush: 'post'
    }
  }
}

5.可以通过组件实例的 $watch() 来命令式地创建一个侦听器

6.用 watch 选项或者 $watch() 实例方法声明的侦听器,会在宿主组件卸载时自动停止

十三、模版引用

1.ref

可以通过ref属性在一个特定dom元素或子组件实例被挂载后,直接获得它的引用。挂载结束后引用暴露在this.$refs上。只能在组件挂载之后才能访问模版引用。

<script>
export default {
  mounted() {
    this.$refs.input.focus()
  }
}
</script>

<template>
  <input ref="input" />
</template>

2.在v-for中使用模版引用时,相应的引用中包含的值是一个数组,但顺序不保证与源数组相同。

3.ref可以绑定一个函数,会在每次组件更新的时候都被调用,需要使用动态的:ref绑定。当绑定的元素被卸载时,函数也会被调用一次。

十四、组件基础

1.定义一个组件

使用构建步骤时,一般会将vue组件定义在一个单独的.vue文件中,被叫做单文件组件(SFC)。

不使用构建步骤时,使用一个包含vue特定选项的js对象来定义。

//vue
<script>
export default {
  data() {
    return {
      count: 0
    }
  }
}
</script>

<template>
  <button @click="count++">You clicked me {{ count }} times.</button>
</template>
//js
export default {
  data() {
    return {
      count: 0
    }
  },
  template: `
    `
}

2.使用一个组件

要使用一个子组件,需要在父组件中导入它,同时要将导入的组件暴露给模版,需要在components上注册这个组件,这个组件会以注册时的名字作为模版中的标签名。

组件可以被重用多次,每个组件都维护自己的状态,每当使用一个组件,就是创建了一个新的实例。

单文件组件中推荐子组件使用驼峰命名,区分大小写,可以使用/>关闭一个标签。

3.传递props

在组件的props列表中声明要传递的值,当这个值被传递给props时,将成为该组件实例的一个属性,可以像其他组件属性一样,在模版和组件的this上下文中访问。

可以拥有任意多的props,接受任意类型的值,被注册后,可以以自定义属性的形势传递数据给它。

4.监听事件

父组件通过v-on:事件、@事件来选择性地监听子组件上抛的事件。

子组件通过调用内置的$emit方法,通过传入事件名称来抛出一个事件。

5.插槽

通过插槽可以像html元素一样向组件中传递内容,可以通过作为一个占位符,父组件传递进来的内容就会渲染在这里。

//template
<AlertBox>
  Something bad happened.
</AlertBox>
//js
<template>
  <div class="alert-box">
    <strong>This is an Error for Demo Purposes</strong>
    <slot />
  </div>
</template>

<style scoped>
.alert-box {
  /* ... */
}
</style>

6.动态组件

通过元素和is来实现。被传递给:is的值可以是被注册的组件名,导入的组件对象。

当使用 来在多个组件间作切换时,被切换掉的组件会被卸载。

你可能感兴趣的:(vue.js)