目录
Vue3 教程
Vue3 教程 官网
Vue3 入门指南与实战案例
vue create 名称
cd 所在文件夹
npm run serve
- 在浏览器中打开提供的网站
- 在index.html编写,每次保存网站都会更新
<!--在 head 中-->
<!--在 HTML 页面中引入 Vue 的 JS 文件-->
<script src="https://unpkg.com/vue@next"></script>
<!--在 HTML 页面中引入 Vue 路由-->
<script src="https://unpkg.com/vue-router@4"></script>
<!--在 HTML 页面中引入 axios -->
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script src="https://cdn.staticfile.org/axios/0.18.0/axios.min.js"></script>
错误
报错:‘xxxx‘ is declared but its value is never read.Vetur(6133)
路径
Vue文件中引用路径:
./
当前文件同级目录@
可以使用 @ 代替 /src 目录,避免易错的相对路径
//vite.config.ts
import { defineConfig } from 'vite';
export default defineConfig({
resolve: {
alias: {
'@': path.resolve(__dirname, 'src') // 设置`@`指向`src`
}
}
})
//vue.config.js
chainWebpack(config) {
config.resolve.alias
.set('@', resolve('src'))
.set('assets', resolve('src/assets'))
.set('utils', resolve('src/utils'));
},
组件
Vue3 中的应用是通过使用 createApp 函数来创建的,参数是根组件(例:HelloVueApp)
Vue.createApp({...}).mount('#hello-vue')
const HelloVueApp = {...}
Vue.createApp(HelloVueApp).mount('#hello-vue')
const HelloVueApp = {...}
const app = Vue.createApp(HelloVueApp)
app.mount('#hello-vue') //hello-vue与app不要取一样的名字,不然会错,页面全空白就是有错误
以上三种表示一个应用需要被挂载到一个 DOM 元素中,以上代码使用 mount('#hello-vue')
将 Vue 应用 HelloVueApp
挂载到 <div id="hello-vue"></div>
中。
自定义组件
//全局组件
const app = Vue.createApp({...})
app.component('my-component-name', {...}) //my-component-name 为组件名
//调用该组件
<my-component-name></my-component-name>
//局部组件
var runoobA = {...}
const app = Vue.createApp({
components: {
'runoob-a': runoobA
}
})
//调用该组件
<runoob-a></runoob-a>
组件属性汇总
const myMixin = {} //要混入的组件
const helloworld = {
data() {return {count: 2}}, //data() 选项
methods: {}, //methods 方法属性,包含了所需方法的对象
computed: {}, //computed 计算属性
watch: {}, //watch 监听属性
mixins: [myMixin] //mixins 混入属性
}
vm = Vue.createApp(helloworld).mount('#hello')
vm.$watch('对象',function(...)){...} //组件里面没写watch也能有这条
vm.$data.count = 6
//自定义组件
const app = Vue.createApp({})
// 定义一个名为 runoob的新全局组件
app.component('runoob', { //除了可以有上面的属性外,还有:
props: ['title'], //props属性:把数据传给子组件
//单行用单引号 //template属性:子组件
template: '<h1>{{ title }}</h1>',
//多行用反引号
template: `
<button @click="count++">
点了 {{ count }} 次!
</button>`,
//各种钩子函数
// 在绑定元素的 attribute 或事件监听器被应用之前调用
created() {},
// 在绑定元素的父组件挂载之前调用
beforeMount() {},
// 绑定元素的父组件被挂载时调用
mounted() {},
// 在包含组件的 VNode 更新之前调用
beforeUpdate() {},
// 在包含组件的 VNode 及其子组件的 VNode 更新之后调用
updated() {},
// 在绑定元素的父组件卸载之前调用
beforeUnmount() {},
// 卸载绑定元素的父组件时调用
unmounted() {}
})
app.mount('#hello')
钩子函数
Vue3生命周期钩子(hooks)完整指南
Vue3.x 的生命周期和钩子函数
指令定义函数提供了几个钩子函数:
- 导入:
import { onActivated, onMounted } from 'vue'
- 钩子函数更新:
Vue2--------------vue3
beforeCreate -> setup()
created -> setup()
beforeMount -> onBeforeMount
mounted -> onMounted
beforeUpdate -> onBeforeUpdate
updated -> onUpdated
beforeDestroy -> onBeforeUnmount
destroyed -> onUnmounted
activated -> onActivated
deactivated -> onDeactivated
errorCaptured -> onErrorCaptured
- 功能
setup()
:开始创建组件之前,在beforeCreate
和created
之前执行。创建的是data
和method
onBeforeMount()
: 组件挂载到节点上之前执行的函数。
onMounted()
: 组件挂载完成后执行的函数。
onBeforeUpdate()
: 组件更新之前执行的函数。
onUpdated()
: 组件更新完成之后执行的函数。
onBeforeUnmount()
: 组件卸载之前执行的函数。
onUnmounted()
: 组件卸载完成后执行的函数
onActivated()
: 被包含在<keep-alive>
中的组件,会多出两个生命周期钩子函数。被激活时执行。例如,使用keep-alive管理不同的tab视图,每次切换tab时,当前的tab将会触发activated钩子。使用组件会将数据保留在内存中,比如我们不想每次看到一个页面都重新加载数据,就可以使用组件解决。
onDeactivated()
: 比如从 A 组件,切换到 B 组件,A 组件消失时执行。
onErrorCaptured()
: 当捕获一个来自子孙组件的异常时激活钩子函数(以后用到再讲,不好展现)。
钩子函数的参数有:
- el:el 指令绑定到的元素。这可用于直接操作 DOM。
- binding:binding 是一个对象,包含以下属性:
- instance:使用指令的组件实例。
- value:传递给指令的值。例如,在 v-my-directive=“1 + 1” 中,该值为 2。
- oldValue:先前的值,仅在 beforeUpdate 和 updated 中可用。值是否已更改都可用。
- arg:参数传递给指令 (如果有)。例如在 v-my-directive:foo 中,arg 为 “foo”。
- modifiers:包含修饰符 (如果有) 的对象。例如在 v-my-directive.foo.bar 中,修饰符对象为 {foo: true,bar: true}。
- dir:一个对象,在注册指令时作为参数传递。
- vnode:作为 el 参数收到的真实 DOM 元素的蓝图。
- prevNode:上一个虚拟节点,仅在 beforeUpdate 和 updated 钩子中可用。
import { createApp } from 'vue'
const app = createApp({})
// 注册
app.directive('my-directive', {
// 指令是具有一组生命周期的钩子:
// 在绑定元素的 attribute 或事件监听器被应用之前调用
created() {},
// 在绑定元素的父组件挂载之前调用
beforeMount() {},
// 绑定元素的父组件被挂载时调用
mounted() {},
// 在包含组件的 VNode 更新之前调用
beforeUpdate() {},
// 在包含组件的 VNode 及其子组件的 VNode 更新之后调用
updated() {},
// 在绑定元素的父组件卸载之前调用
beforeUnmount() {},
// 卸载绑定元素的父组件时调用
unmounted() {}
})
// 注册 (功能指令)
app.directive('my-directive', () => {
// 这将被作为 `mounted` 和 `updated` 调用
})
// getter, 如果已注册,则返回指令定义
const myDirective = app.directive('my-directive')
不要在选项 property 或回调上使用箭头函数,比如 created: () => console.log(this.a) 或
vm.$watch(‘a’, newValue => this.myMethod())。因为箭头函数并没有 this,this
会作为变量一直向上级词法作用域查找,直至找到为止,经常导致 Uncaught TypeError: Cannot read property
of undefined 或 Uncaught TypeError: this.myMethod is not a function
之类的错误。
props 属性
Props
通过 Prop 向子组件传递数据
<!-- 包含该 prop 没有值的情况在内,都意味着 `true` -->
<!-- 如果没有在 props 中把 is-published 的类型设置为 Boolean,则这里的值为空字符串,而不是“true”。 -->
<blog-post is-published></blog-post>
<div id="app">
<site-name title="Google"></site-name>
<site-name title="Runoob"></site-name>
<site-name title="Taobao"></site-name>
</div>
<script>
const app = Vue.createApp({})
app.component('site-name', { //局部组件site-name是父组件
props: ['title'], //父组件的数据通过 props 把数据传给子组件
template: `<h4>{{ title }}</h4>` //子组件
})
app.mount('#app')
</script>
<!--也可以用 v-bind 动态绑定 props 的值到父组件的数据中。
每当父组件的数据变化时,该变化也会传导给子组件-->
<div id="app">
<site-info
v-for="site in sites"
:id="site.id" <!--v-bind 的缩写-->
:title="site.title"
></site-info>
</div>
<script>
const Site = {
data() {
return {
sites: [
{ id: 1, title: 'Google' },
{ id: 2, title: 'Runoob' },
{ id: 3, title: 'Taobao' }
]
}
}
}
const app = Vue.createApp(Site)
app.component('site-info', {
props: ['id','title'],
template: `<h4>{{ id }} - {{ title }}</h4>`
})
app.mount('#app')
</script>
//可以为 props 中的值提供一个带有验证需求的对象,而不是一个字符串数组。例如:
Vue.component('my-component', {
props: {
// 基础的类型检查 (`null` 和 `undefined` 会通过任何类型验证)
propA: Number,
// 多个可能的类型
propB: [String, Number],
// 必填的字符串
propC: {
type: String,
required: true
},
// 带有默认值的数字
propD: {
type: Number,
default: 100
},
// 带有默认值的对象
propE: {
type: Object,
// 对象或数组默认值必须从一个工厂函数获取
default: function () {
return { message: 'hello' }
}
},
// 自定义验证函数
propF: {
validator: function (value) {
// 这个值必须匹配下列字符串中的一个
return ['success', 'warning', 'danger'].indexOf(value) !== -1
}
}
}
})
type 可以是下面原生构造器:
String
Number
Boolean
Array
Object
Date
Function
Symbol
type 也可以是一个自定义构造器,使用 instanceof 检测。
computed 计算属性
- 可以使用 methods 来替代 computed,效果上两个都是一样的,
- 但是 computed 是基于它的依赖缓存,只有相关依赖发生改变时才会重新取值。
- 而使用 methods ,在重新渲染的时候,函数总会重新调用执行。
- 可以说使用 computed 性能会更好,但是如果你不希望缓存,你可以使用 methods 属性。
computed 属性默认只有 getter ,不过在需要时你也可以提供一个 setter :
//例子
computed: {
site: {
// getter
get: function () {
return this.name + ' ' + this.url
},
// setter
set: function (newValue) {
var names = newValue.split(' ')
this.name = names[0]
this.url = names[names.length - 1]
}
}
}
mixins 混入属性
- 混入 (mixins)定义了一部分可复用的方法或者计算属性。混入对象可以包含任意组件选项。当组件使用混入对象时,所有混入对象的选项将被混入该组件本身的选项。
- 全局混入:一旦使用全局混入对象,将会影响到 每个单独创建的 Vue 实例 (包括第三方模板)。使用恰当时,可以为自定义对象注入处理逻辑。
- 选项合并:当组件和混入对象含有同名选项时,这些选项将以恰当的方式混合。
- 数据对象在内部会进行浅合并 (一层属性深度),在和组件的数据发生冲突时以组件数据优先。
- 同名钩子函数将合并为一个数组,因此都将被调用。另外,mixin 对象的钩子将在组件自身钩子之前调用。
- 两个对象键名冲突时,取组件对象的键值对。例如 methods、components 和 directives,将被合并为同一个对象。
// 定义混入对象
const myMixin = {
created() {
this.hello()
},
methods: {
hello() {
console.log('欢迎来到混入实例-RUNOOB!')
}
}
}
// 定义一个应用,使用混入
const app = Vue.createApp({
mixins: [myMixin]
})
app.mount('#app') // => "欢迎来到混入实例-RUNOOB!"
//选项合并
<script type = "text/javascript">
const myMixin = {
data() {
return {
message: 'hello',
foo: 'runoob'
}
}
}
const app = Vue.createApp({
mixins: [myMixin],
data() {
return {
message: 'goodbye',
bar: 'def'
}
},
created() {
document.write(JSON.stringify(this.$data))
}
})
//输出结果为:
{"message":"goodbye","foo":"runoob","bar":"def"}
const myMixin = {
created() {
console.log('mixin 对象的钩子被调用')
}
}
const app = Vue.createApp({
mixins: [myMixin],
created() {
console.log('组件钩子被调用')
}
})
// => "mixin 对象的钩子被调用"
// => "组件钩子被调用"
//
const myMixin = {
methods: {
foo() {
console.log('foo')
},
conflicting() {
console.log('from mixin')
}
}
}
const app = Vue.createApp({
mixins: [myMixin],
methods: {
bar() {
console.log('bar')
},
conflicting() {
console.log('from self')
}
}
})
const vm = app.mount('#app')
vm.foo() // => "foo"
vm.bar() // => "bar"
vm.conflicting() // => "from self"
//全局混入
const app = Vue.createApp({
myOption: 'hello!'
})
// 为自定义的选项 'myOption' 注入一个处理器。
app.mixin({
created() {
const myOption = this.$options.myOption
if (myOption) {
document.write(myOption)
}
}
})
app.mount('#app') // => "hello!"
watch 监听属性
指令
<!-- 在 index.html 的 body 中 -->
<div id="hello-vue">
<p>123456</p>
<!-- 对应组件实例中 message 属性的值-->
<p>{{ message }}</p>
<!-- 可使用JavaScript表达式 -->
<p>{{5+5}}</p>
<!-- 这是语句,不是表达式:-->
<!-- <p>{{var a = 1}}</p> -->
<!-- 流控制也不会生效,请使用三元表达式 -->
<!-- <p>{{ if (true) { return message } }}</p> -->
<!-- 指令:带有 v- 前缀的特殊属性-->
<!-- v-once:执行一次性地插值,当数据改变时,插值处的内容不会更新 -->
<p><span v-once>不会改变: {{ message }}</span> </p>
<!-- v-html:输出 html 代码 ,这里的hhhhhh不会输出-->
<p><span v-html="rawHtml">hhhhhhhhh</span></p>
<!-- v-model:如:用户输入,在 input 输入框中我们可以使用v-model 指令来实现双向数据绑定: -->
<input v-model="message">
<!-- v-show: 来根据条件展示元素 -->
<h1 v-show="ok">Hello!</h1>
<!-- v-bind:双大括号不能在HTML attribute中使用,所以使用 v-bind 指令
v-bind 绑定 HTML 特性到一个表达式-->
<p><div v-bind:id="'list-'">菜鸟教程</div></p>
<p><a v-bind:href="url">菜鸟教程</a></p>
<p><a :href="url">缩写格式</a></p>
<!-- v-on:监听 -->
<button v-on:click="">完整格式</button>
<button @click="">缩写格式</button>
<!-- v-if: 多个元素,可以包裹在 <template> 元素上-->
<p v-if="seen">现在你看到我了</p>
<template v-if="seen">
<h1>网站</h1>
<p>Google</p>
<p>Runoob</p>
<p>Taobao</p>
</template>
<!-- v-else:如 随机生成一个数字,判断是否大于 0.5 -->
<div v-if="Math.random() > 0.5">随机数大于 0.5</div>
<div v-else>随机数小于等于 0.5</div>
<!-- v-else-if -->
<div v-if="type === 'A'">A</div>
<div v-else-if="type === 'B'">B</div>
<div v-else-if="type === 'C'">C</div>
<div v-else>Not A/B/C</div>
<!-- v-for: 需要以 site in sites 形式的特殊语法,
sites 是源数据数组并且 site 是数组元素迭代的别名。
v-for 可以绑定数据到数组来渲染一个列表 -->
<li v-for="site in sites">{{ site.text }}</li>
<li v-for="(site, index) in sites">{{ index }}--{{ site.text }}</li>
<template v-for="site in sites">
<li>{{ site.text }}</li>
<li>--------------</li>
</template>
<li v-for="value in object">{{ value }}</li>
<li v-for="(value, key, index) in object">
{{ index }}. {{ key }} : {{ value }}
</li>
<li v-for="n in 10">{{ n }}</li>
<li v-for="n in evenNumbers">{{ n }}</li>
</div>
<script>
const HelloVueApp = {
//`data` 选项是一个函数。Vue 在创建新组件实例的过程中调用此函数。
//它应该返回一个对象,然后 Vue 会通过响应性系统将其包裹起来,
//并以 $data 的形式存储在组件实例中。
data() {
return {
message: 'Hello V!!',
rawHtml: '<span style="color: red">这里会显示红色!</span>',
seen: true, /* 改为false,信息就无法显示 */
url: 'https://www.runoob.com',
type: "C",
ok: true,
sites: [
{ text: 'Google' },
{ text: 'Runoob' },
{ text: 'Taobao' }
],
object: {
name: '菜鸟教程',
url: 'http://www.runoob.com',
slogan: '123456'
},
numbers: [ 1, 2, 3, 4, 5 ]
}
},
computed: {
evenNumbers() {
return this.numbers.filter(number => number % 2 === 0)
}
}
}
Vue.createApp(HelloVueApp).mount('#hello-vue')
</script>
v-on 指令
- v-on 指令监听 DOM 事件
- v-on 指令可以缩写为 @ 符号
- v-on 指令是事件绑定指令,当用户需要点击,按下键盘,滚动鼠标等操作时,想要添加一些自己的逻辑处理时,就可以为特定的元素绑定一些特定的事件。
- 如果是点击事件就写click,如果是鼠标移入事件就写monseenter,如果是鼠标双击事件就写 dblclick
v-on:click
<div id="hello">
<!-- v-on 指令可以缩写为 @ 符号 -->
<button @click="counter += 1">增加 1</button>
<p>这个按钮被点击了 {{ counter }} 次。</p>
<!-- 接收一个定义的方法来调用 -->
<!-- `greet` 是在下面定义的方法名 -->
<button @click="greet">点我</button>
<!-- 用内联 JavaScript 语句 -->
<button @click="say('hi')">Say hi</button>
<!-- 事件处理程序中可以有多个方法,这些方法由逗号运算符分隔 -->
<button @click="one($event), two($event)">点我</button>
</div>
<script>
const helloworld = {
data() {
return {
counter: 0,
name: 'Runoob'
}
},
methods: {
greet(event) {
// `methods` 内部的 `this` 指向当前活动实例
alert('Hello ' + this.name + '!')
// `event` 是原生 DOM event
if (event) {
alert(event.target.tagName)
}
},
say(message) {
alert(message)
},
one(event) {
alert("第一个事件处理器逻辑...")
},
two(event) {
alert("第二个事件处理器逻辑...")
}
}
}
Vue.createApp(helloworld).mount('#hello')
</script>
- 事件修饰符
v-on 提供了事件修饰符来处理 DOM 事件细节
.stop - 阻止冒泡
.prevent - 阻止默认事件
.capture - 阻止捕获
.self - 只监听触发该元素的事件
.once - 只触发一次
.left - 左键事件
.right - 右键事件
.middle - 中间滚轮事件 - 按键修饰符
Vue 允许为 v-on 在监听键盘事件时添加按键修饰符
全部的按键别名:
.enter
.tab
.delete (捕获 “删除” 和 “退格” 键)
.esc
.space
.up
.down
.left
.right
系统修饰键:
.ctrl
.alt
.shift
.meta
鼠标按钮修饰符:
.left
.right
.middle - .exact 修饰符
.exact 修饰符允许你控制由精确的系统修饰符组合触发的事件。
实例
<!-- 即使 Alt 或 Shift 被一同按下时也会触发 -->
<button @click.ctrl="onClick">A</button>
<!-- 有且只有 Ctrl 被按下的时候才触发 -->
<button @click.ctrl.exact="onCtrlClick">A</button>
<!-- 没有任何系统修饰符被按下的时候才触发 -->
<button @click.exact="onClick">A</button>
v-bind 指令
- 在需要动态绑定的属性前面加上v-bind就会自动去vue实例里面去找当前的属性去进行设置
- 表示绑定这个属性,绑定之后,对应的值要去vue的数据里面找,当然也可以等于一个常数,这样就不用去data里找了。
v-bind:
可以省略成:
v-model 指令
v-model 相当于 v-on 和 v-bind
//例如:可以使用v-model 指令来实现双向数据绑定
<input v-model="test">
//本质上是
<input
:value="test"
@input="test => $event.target.value"
>
//v-on:在 input 发生时,会触发 test = $event.target.value 事件
//v-bind:给属性 value 绑定 test 实例
- v-model 会根据控件类型自动选取正确的方法来更新元素。
- v-model 会忽略所有表单元素的 value、checked、selected 属性的初始值,使用的是 data 选项中声明初始值。
- v-model 在内部为不同的输入元素使用不同的属性并抛出不同的事件:
select
:使用 value 属性和 change 事件。text
和textarea
:使用 value 属性和 input 事件;checkbox
和radio
:使用 checked 属性和 change 事件;
<input v-model="message" placeholder="编辑我……">
<p>input 表单消息是: {{ message }}</p>
<textarea v-model="message2" placeholder="多行文本输入……"></textarea>
<p>textarea 表单消息是:</p>
<p style="white-space: pre">{{ message2 }}</p>
//
data() {
return {
message: '',
message2: '菜鸟教程\r\nhttps://www.runoob.com'
}
}
在文本区域 textarea 插值是不起作用,需要使用 v-model 来代替:
<!-- 错误 -->
<textarea>{{ text }}</textarea>
<!-- 正确 -->
<textarea v-model="text"></textarea>
复选框如果是一个为逻辑值,如果是多个则绑定到同一个数组:
<input type="checkbox" id="checkbox" v-model="checked">
<input type="checkbox" id="runoob" value="Runoob" v-model="checkedNames">
<label for="runoob">Runoob</label>
<input type="checkbox" id="google" value="Google" v-model="checkedNames">
<label for="google">Google</label>
<input type="checkbox" id="taobao" value="Taobao" v-model="checkedNames">
<label for="taobao">taobao</label>
//
data() {
return {
checked : false,
checkedNames: []
}
}
单选按钮的双向数据绑定
<input type="radio" id="runoob" value="Runoob" v-model="picked">
//
data() {
return {
picked : 'Runoob'
}
}
下拉列表的双向数据绑定
<select v-model="selected" name="site">
<option value="">选择一个网站</option>
<option value="www.runoob.com">Runoob</option>
<option value="www.google.com">Google</option>
</select>
//
data() {
return {
selected: ''
}
}
多选时会绑定到一个数组
<select v-model="selected" name="fruit" multiple>
<option value="www.runoob.com">Runoob</option>
<option value="www.google.com">Google</option>
<option value="www.taobao.com">Taobao</option>
</select>
//
selected: ''
v-for 循环输出选项
<select v-model="selected">
<option v-for="option in options" :value="option.value">
{{ option.text }}
</option>
</select>
//
selected: 'www.runoob.com',
options: [
{ text: 'Runoob', value: 'www.runoob.com' },
{ text: 'Google', value: 'www.google.com' },
{ text: 'Taobao', value: 'www.taobao.com' }
]
值绑定
对于单选按钮,复选框及选择框的选项,v-model 绑定的值通常是静态字符串 (对于复选框也可以是布尔值):
但是有时我们可能想把值绑定到当前活动实例的一个动态属性上,这时可以用 v-bind 实现,此外,使用 v-bind 可以将输入值绑定到非字符串。
//复选框 (Checkbox):
<input type="checkbox" v-model="toggle" true-value="yes" false-value="no" />
...
// 选中时
vm.toggle === 'yes'
// 取消选中
vm.toggle === 'no'
//单选框 (Radio):
<input type="radio" v-model="pick" v-bind:value="a" />
// 当选中时
vm.pick === vm.a
//选择框选项 (Select):
<select v-model="selected">
<!-- 内联对象字面量 -->
<option :value="{ number: 123 }">123</option>
</select>
// 当被选中时
typeof vm.selected // => 'object'
vm.selected.number // => 123
修饰符
.lazy
在默认情况下, v-model 在 input 事件中同步输入框的值与数据,但你可以添加一个修饰符 lazy ,从而转变为在 change 事件中同步:
<!-- 在 "change" 而不是 "input" 事件中更新 -->
<input v-model.lazy="msg" >
.number
如果想自动将用户的输入值转为 Number 类型(如果原值的转换结果为 NaN 则返回原值),可以添加一个修饰符 number 给 v-model 来处理输入值:
<input v-model.number="age" type="number">
这通常很有用,因为在 type=“number” 时 HTML 中输入的值也总是会返回字符串类型。
.trim
如果要自动过滤用户输入的首尾空格,可以添加 trim 修饰符到 v-model 上过滤输入:
<input v-model.trim="msg">
自定义指令
默认设置的核心指令( v-model 和 v-show )
<!--注册一个全局指令 v-focus, 该指令的功能是在页面加载时,元素获得焦点:-->
<div id="app">
<p>页面载入时,input 元素自动获取焦点:</p>
<input v-focus>
</div>
<script>
// 注册一个全局自定义指令 `v-focus`
const app = Vue.createApp({})
app.directive('focus', {
// 当被绑定的元素挂载到 DOM 中时……
mounted(el) {
// 聚焦元素
el.focus()
}
})
//可以在实例使用 directives 选项来注册局部指令,这样指令只能在这个实例中使用
const app = {
data() {
return { }
},
directives: {
focus: {
// 指令的定义
mounted(el) {
el.focus()
}
}
}
}
app.mount('#app')
</script>
样式绑定
class
class 与 style 是 HTML 元素的属性,用于设置元素的样式,我们可以用 v-bind 来设置样式属性
- :class 指令也可以与普通的 class 属性共存。
- 在带有单个根元素的自定义组件上使用 class 属性时,这些 class 将被添加到该元素中。此元素上的现有 class 将不会被覆盖
- 如果你的组件有多个根元素,你需要定义哪些部分将接收这个类。可以使用 $attrs 组件属性执行此操作
<!DOCTYPE html>
<html lang="">
<head>
<meta charset="utf-8">
<script src="https://unpkg.com/vue@next"></script>
<style>
.static {
width: 100px;
height: 100px;
}
.active {
background: green;
}
.text-danger {
background: red;
}
</style>
</head>
<body>
<div id="hello">
<!-- 为 v-bind:class 设置一个对象,从而动态的切换 class -->
<div class="static" :class="{ 'active': isActive }"></div>
<!-- 在对象中传入更多属性用来动态切换多个 class -->
<div class="static" :class="{ 'active' : isActive, 'text-danger' : hasError }"></div>
<!-- 直接绑定数据里的一个对象 -->
<div class="static" :class="classObject"></div>
<!-- 绑定一个返回对象的计算属性 -->
<div class="static" :class="classObject2"></div>
<!-- 可以把一个数组传给 v-bind:class -->
<div class="static" :class="[activeClass, errorClass]"></div>
<!-- 三元表达式来切换列表中的 class -->
<div class="static" :class="[isActive ? activeClass : '', errorClass]"></div>
</div>
<script>
const helloworld = {
data() {
return {
isActive: true,
hasError: false,
classObject: {
'active': false,
'text-danger': true
},
error: null,
activeClass: 'active',
errorClass: 'text-danger'
}
},
computed: {
classObject2() {
return {
active: this.isActive && !this.error,
'text-danger': this.error && this.error.type === 'fatal'
}
}
}
}
Vue.createApp(helloworld).mount('#hello')
</script>
</body>
</html>
style
<div id="hello">
<!-- 在 v-bind:style 直接设置样式,可以简写为 :style: -->
<div :style="{ color: activeColor, fontSize: fontSize + 'px' }">111</div>
<!-- 直接绑定到一个样式对象,让模板更清晰: -->
<div :style="styleObject">222</div>
<!-- v-bind:style 可以使用数组将多个样式对象应用到一个元素上: -->
<div :style="[baseStyles, overridingStyles]">333</div>
<!-- 可以为 style 绑定中的 property 提供一个包含多个值的数组,常用于提供多个带前缀的值,
这样写只会渲染数组中最后一个被浏览器支持的值。在本例中,如果浏览器支持不带浏览器前缀的 flexbox,那么就只会渲染 display: flex。 -->
<div :style="{ display: ['-webkit-box', '-ms-flexbox', 'flex'] }"></div>
</div>
<script>
const helloworld = {
data() {
return {
activeColor: 'red',
fontSize: 30,
styleObject: {
color: "red",
fontSize: "30px"
},
baseStyles: {
color: 'green',
fontSize: '30px'
},
overridingStyles: {
'font-weight': 'bold'
}
}
}
}
Vue.createApp(helloworld).mount('#hello')
</script>
router 路由
<script src="https://unpkg.com/vue@next"></script>
<script src="https://unpkg.com/vue-router@4"></script>
<router-link>
组件用于设置一个导航链接,切换不同 HTML 内容。不用 a 标签 可以在不重新加载页面的情况下更改 URL
<router-view>
将显示与 url 对应的组件
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Vue 测试实例 - 菜鸟教程(runoob.com)</title>
<script src="https://unpkg.com/vue@next"></script>
<script src="https://unpkg.com/vue-router@4"></script>
</head>
<body>
<div id="app">
<p>
<!--使用 router-link 组件进行导航 -->
<!--通过传递 `to` 来指定链接 -->
<!--`<router-link>` 将呈现一个带有正确 `href` 属性的 `<a>` 标签-->
<router-link to="/">Go to Home</router-link>
<router-link to="/about">Go to About</router-link>
</p>
<!-- 路由出口 -->
<!-- 路由匹配到的组件将渲染在这里 -->
<router-view></router-view>
</div>
<script>
// 1. 定义路由组件.
// 也可以从其他文件导入
const Home = { template: '<div>Home</div>' }
const About = { template: '<div>About</div>' }
// 2. 定义一些路由
// 每个路由都需要映射到一个组件。
// 我们后面再讨论嵌套路由。
const routes = [
{ path: '/', component: Home },
{ path: '/about', component: About },
]
// 3. 创建路由实例并传递 `routes` 配置
// 你可以在这里输入更多的配置,但我们在这里
// 暂时保持简单
const router = VueRouter.createRouter({
// 4. 内部提供了 history 模式的实现。为了简单起见,我们在这里使用 hash 模式。
history: VueRouter.createWebHashHistory(),
routes, // `routes: routes` 的缩写
})
// 5. 创建并挂载根实例
const app = Vue.createApp({})
//确保 _use_ 路由实例使
//整个应用支持路由。
app.use(router)
app.mount('#app')
// 现在,应用已经启动了!
</script>
</body>
</html>
to 属性为目标地址, 即要显示的内容,当被点击后,内部会立刻把 to 的值传到 router.push(),所以这个值可以是一个字符串或者是描述目标位置的对象。
<!-- 字符串 -->
<router-link to="home">Home</router-link>
<!-- 渲染结果 -->
<a href="home">Home</a>
<!-- 使用 v-bind 的 JS 表达式 -->
<router-link v-bind:to="'home'">Home</router-link>
<!-- 不写 v-bind 也可以,就像绑定别的属性一样 -->
<router-link :to="'home'">Home</router-link>
<!-- 同上 -->
<router-link :to="{ path: 'home' }">Home</router-link>
<!-- 命名的路由 -->
<router-link :to="{ name: 'user', params: { userId: 123 }}">User</router-link>
<!-- 带查询参数,下面的结果为 /register?plan=private -->
<router-link :to="{ path: 'register', query: { plan: 'private' }}">Register</router-link>
replace
设置 replace 属性的话,当点击时,会调用 router.replace() 而不是 router.push(),导航后不会留下 history 记录。
<router-link :to="{ path: '/abc'}" replace></router-link>
append
设置 append 属性后,则在当前 (相对) 路径前添加其路径。例如,我们从 /a 导航到一个相对路径 b,如果没有配置 append,则路径为 /b,如果配了,则为 /a/b
<router-link :to="{ path: 'relative/path'}" append></router-link>
tag
有时候想要 渲染成某种标签,例如
- 。 于是我们使用 tag prop 类指定何种标签,同样它还是会监听点击,触发导航。
-
<router-link to="/foo" tag="li">foo</router-link> <!-- 渲染结果 --> <li>foo</li>
active-class
设置 链接激活时使用的 CSS 类名。可以通过以下代码来替代。<style> ._active{ background-color : red; } </style> <p> <router-link v-bind:to = "{ path: '/route1'}" active-class = "_active">Router Link 1</router-link> <router-link v-bind:to = "{ path: '/route2'}" tag = "span">Router Link 2</router-link> </p>
注意这里 class 使用 active-class=“_active”。
exact-active-class
配置当链接被精确匹配的时候应该激活的 class。可以通过以下代码来替代。<p> <router-link v-bind:to = "{ path: '/route1'}" exact-active-class = "_active">Router Link 1</router-link> <router-link v-bind:to = "{ path: '/route2'}" tag = "span">Router Link 2</router-link> </p>
event
声明可以用来触发导航的事件。可以是一个字符串或是一个包含字符串的数组。<router-link v-bind:to = "{ path: '/route1'}" event = "mouseover">Router Link 1</router-link>
以上代码设置了 event 为 mouseover ,及在鼠标移动到 Router Link 1 上时导航的 HTML 内容会发生改变。
响应式系统
vue3 reactive函数
vue3 中 reactive 注意点(系列四)
vue3
同:将数据变成响应式数据
异:ref用于基本数据类型,reactive是用于复杂数据类型,如对象和数组reactive
import { reactive, ref } from 'vue';
参数:必须是 json 对象或数组
本质:就是将传入的数据包装成一个Proxy对象
基本类型(数字、字符串、布尔值)在 reactive 中无法被创建成 proxy 对象,也就无法实现监听,无法实现响应式
(proxy 见 es6)ref
引用实例
ref()
ref([])
平时我们在定义变量的时候,都是这样给他们进行类型声明的:// 单类型 const msg: string = 'Hello World!'; // 多类型 const phoneNumber: number | string = 13800138000;
但是在使用 ref 时,不能这样子声明,会报错,正确的声明方式应该是使用 <> 来包裹类型定义,紧跟在 ref API 之后:
// 单类型 const msg = ref<string>('Hello World!'); // 多类型 const phoneNumber = ref<number | string>(13800138000);
Ajax(axios)
Vue3 Ajax(axios)
get 方法读取 JSON 数据,response.data 读取 JSON 数据
get 方法传递参数格式
post 方法读取 PHP 数据
post 方法传递参数格式未完待续
watch
axios
自定义事件