官网:https://vue3js.cn/docs/zh/guide/instance.html
一、应用实例 & 组件实例:
1、Vue3 以 Vue.createApp 创建 vue实例的【不是 Vue2 的new Vue 创建】,参数就是 根组件实例。
const app = Vue.createApp({ /* 选项 */ })
2、应用实例暴露的大多数方法都会返回该同一实例,允许链式:
Vue.createApp({}) .component('SearchInput', SearchInputComponent) .directive('focus', FocusDirective) .use(LocalePlugin)
3、Vue挂载应用,使用 mount 方法:与大多数应用方法不同的是,mount
不返回应用本身。相反,它返回的是根组件实例。
const vm = app.mount('#app') // vm 是根组件实例,而不是 应用实例
注意:不要在选项 property 或回调上使用 箭头函数,比如 created: () => console.log(this.a)
或 vm.$watch('a', newValue => this.myMethod())
。因为箭头函数并没有 this,
this
会作为变量一直向上级词法作用域查找,直至找到为止。
二、模板语法:
1、指令 动态参数:【指令 的动态参数 很少使用到】
<a v-bind:[attributeName]="url"> ... </a> // attributeName是 组件的 property 值,即vue的 data变量。如,令 attributeName="href",那么这个绑定将等价于 v-bind:href
同样事件的 绑定也可以是动态的:
<a v-on:[eventName]="doSomething"> ... </a>
三、Class 与 Style 绑定:
1、在组件上 绑定 HTML Class:
如果你的组件有多个根元素【vue2的组件只有一个根元素,vue3是可以多个根元素的】,你需要定义哪些部分将接收这个类。可以使用 $attrs
组件属性执行此操作:
<div id="app"> <my-component class="baz"></my-component> </div>
const app = Vue.createApp({}) app.component('my-component', { template: ` <p :class="$attrs.class">Hi!</p> <span>This is a child component</span> ` })
四、事件处理
1、事件修饰符:
-
.stop
.prevent
.capture
.self
.once
.passive
2、按键修饰符:你可以直接将 KeyboardEvent.key
暴露的任意有效按键名转换为 kebab-case 来作为修饰符。
<input @keyup.page-down="onPageDown" />
按键别名:(Vue 为最常用的键提供了别名)
-
.enter
.tab
.delete
(捕获“删除”和“退格”键).esc
.space
.up
.down
.left
.right
3、系统修饰键:可以用如下修饰符来实现仅在按下相应按键时才触发鼠标或键盘事件的监听器。
-
.ctrl
.alt
.shift
.meta
<!-- Alt + Enter --> <input @keyup.alt.enter="clear" /> <!-- Ctrl + Click --> <div @click.ctrl="doSomething">Do something</div>
4、.exact
修饰符: 修饰符允许你控制由精确的系统修饰符组合触发的事件
<!-- 即使 Alt 或 Shift 被一同按下时也会触发 --> <button @click.ctrl="onClick">A</button> <!-- 有且只有 Ctrl 被按下的时候才触发 --> <button @click.ctrl.exact="onCtrlClick">A</button> <!-- 没有任何系统修饰符被按下的时候才触发 --> <button @click.exact="onClick">A</button>
5、鼠标按钮修饰符:
-
.left
.right
.middle
五、表单输入绑定:
1、修饰符:
-
-
.lazy 【在默认情况下,
v-model
在每次input
事件触发后将输入框的值与数据进行同步。添加这个修饰符,可以变成 change 事件 之后 进行同步】 .number 【自动将用户的输入值转为数值类型,默认文本框获取到的值都是字符串】
.trim 【自动过滤用户输入的首尾空白字符】
-
六、非 Prop 的 Attribute:一个非 prop 的 attribute 是指传向一个组件,但是该组件并没有相应 props 或 emits 定义的 attribute。常见的示例包括 class
、style
和 id
属性 以及自定义属性。
1、Attribute 继承:当组件返回单个根节点时,非 prop attribute 将自动添加到根节点的 attribute 中。
2、禁用 Attribute 继承:如果你不希望组件的根元素继承 attribute,你可以在组件的选项中设置 inheritAttrs: false
。
app.component('date-picker', { inheritAttrs: false, template: ` <div class="date-picker"> <input type="datetime" v-bind="$attrs" /> </div> ` })
3、多个根节点上的 Attribute 继承:与单个根节点组件不同,具有多个根节点的组件不具有自动 attribute 回退行为。如果未显式绑定 $attrs
,将发出运行时警告。
// 没有警告,$attrs被传递到<main>元素 app.component('custom-layout', { template: ` <header>...</header> <main v-bind="$attrs">...</main> <footer>...</footer> ` })
七、自定义事件:【组件标签中才会使用自定义事件,原生标签中没有自定义事件】
1、推荐 始终使用 kebab-case 的事件名,即自定义的事件名,使用 kebab-case 命名【全部小写的,短横线命名】。
2、自定义组件的 v-model:【组件标签的 v-model 修改 才意义;原生标签中 无法修改v-model传递参数,也没有意义】
默认情况下,组件上的 v-model
使用 modelValue
作为 prop 和 update:modelValue
作为事件。我们可以通过向 v-model
传递参数来修改这些名称:
分析:默认情况 v-model 中 v-bind 绑定的 modelValue属性【vue2中绑定的是value属性】。通过 v-model 传递参数,可以修改v-model绑定的props 属性名。
<my-component v-model:foo="bar"></my-component>
const app = Vue.createApp({}) app.component('my-component', { props: { foo: String }, template: ` <input type="text" :value="foo" @input="$emit('update:foo', $event.target.value)"> ` })
3、组件上多个 v-model 绑定:基于上面讲的 通过向 v-model 传递参数,可以修改 v-model 绑定不同的 属性。从而实现 组件中 可以 多个 变量 实现双向绑定。
<user-name v-model:first-name="firstName" v-model:last-name="lastName" ></user-name>
const app = Vue.createApp({}) app.component('user-name', { props: { firstName: String, lastName: String }, template: ` <input type="text" :value="firstName" @input="$emit('update:firstName', $event.target.value)"> <input type="text" :value="lastName" @input="$emit('update:lastName', $event.target.value)"> ` })
八、插槽
1、插槽 渲染作用域: 插槽 里面 变量的作用域 是 其 所在模板中 作用域。不能访问 子组件内的作用域。
<todo-button action="delete"> Clicking here will {{ action }} an item <!-- `action` 未被定义,因为它的内容是传递*到* <todo-button>。 --> </todo-button>
规则:父级模板里的所有内容都是在父级作用域中编译的;子模板里的所有内容都是在子作用域中编译的。
2、插槽的 后备内容:在插槽没有提供内容的时候被渲染。【在 slot 没有内容输入进来时,就会渲染 slot 里面默认是值】
<button type="submit"> <slot>Submit</slot> </button>
3、具名插槽: <slot> 元素有一个特殊的 attribute:name; 一个不带 name 的 <slot> 出口会带有隐含的名字“default”。
<div class="container"> <header> <slot name="header"></slot> </header> <main> <slot></slot> </main> <footer> <slot name="footer"></slot> </footer> </div>
4、作用域插槽【让插槽内容能访问子组件的数据】:默认是 无法访问的,通过给 slot 设置 插槽 prop。就可以把 子组件的 数据,传递到 插槽内容上。 详细内容,看文档
<current-user> <template v-slot:default="slotProps"> {{ slotProps.user.firstName }} </template> </current-user>
5、动态插槽名:
<base-layout> <template v-slot:[dynamicSlotName]> ... </template> </base-layout>
6、具名插槽的缩写: 跟 v-on
和 v-bind
一样,v-slot
也有缩写,即把参数之前的所有内容 (v-slot:
) 替换为字符 #
。
<base-layout> <template #header> <h1>Here might be a page title</h1> </template> </base-layout>
九、提供 / 注入【provide 和 inject】:
父组件可以作为其所有子组件的依赖项提供程序,而不管组件层次结构有多深。这个特性有两个部分:父组件有一个 provide
选项来提供数据,子组件有一个 inject
选项来开始使用这个数据。
1、处理响应性:
app.component('todo-list', { // ... provide() { return { todoLength: Vue.computed(() => this.todos.length) } } })
十、