<template>
<div>
<p>文本插值 {{ mesage }}p>
<p>JS表达式 {{ flag ? 'yes' : 'no' }}p>
<p :id="dynamicId">动态属性 idp>
<p v-html="rawHtml">
<span>【注意】使用 v-html 之后,将会覆盖子元素span>
p>
div>
template>
<script>
export default {
data() {
return {
message: 'hello',
flag: true,
rawHtml: '这是加粗这是斜体',
dynamicId: `id-${Date.now()}`
}
}
}
script>
<style scoped>
style>
<template>
<div>
<p>num {{ num }}p>
<p>double1 {{ double1 }}p>
<input v-model="double2" />
div>
template>
<script>
export default {
data() {
return {
num: 20
}
},
computed: {
double1() {
return this.num * 2
},
// v-model 绑定的话需要写 get set
double2: {
get() {
return this.num * 2
},
set(val) {
return this.num = val / 2
}
}
}
}
script>
<style scoped>
style>
<template>
<div>
<input v-model="name" />
<input v-model="info.city" />
div>
template>
<script>
export default {
data() {
return {
name: 'Jae',
info: {
city: 'xx'
}
}
},
computed: {},
watch: {
name(oldVal, val) {
console.log('watch name', oldVal, val) // 值类型,可以正常拿到 oldVal 和 val
},
info: {
handler(oldVal, val) {
console.log('watch info', oldVal, val) // 引用类型,拿不到 oldVal。因为指针相同,此时已经指向了新的 val
},
deep: true // 深度监听
}
}
}
script>
<style scoped>
style>
<template>
<div>
<p :class="{ black: isBack, yellow: isYellow }">使用 classp>
<p :class="[ black, yellow ]">使用 class(数组)p>
<p :style="styleData">使用 stylep>
div>
template>
<script>
export default {
data() {
return {
isBack: true,
isYellow: true,
black: 'black',
yellow: 'yellow',
styleData: {
fontSize: '40px', // 驼峰
color: 'red',
backgroundColor: '#ccc' // 驼峰
}
}
}
}
script>
<style scoped>
style>
<template>
<div>
<p v-if="type === 'a'">Ap>
<p v-else-if="type === 'b'">Bp>
<p v-else>otherp>
<p v-show="type === 'a'">A by v-showp>
<p v-show="type === 'b'">B by v-showp>
div>
template>
<script>
export default {
data() {
return {
type: 'a'
}
}
}
script>
<style scoped>
style>
如果页面上需要频繁切换渲染,用 v-show
;如果渲染的次数不频繁,用 v-if
<template>
<div>
<p>遍历数组p>
<ul>
<li v-for="(item, index) in arrList" :key="item.id">
{{ index }} - {{ item.id }} - {{ item.title }}
li>
ul>
<p>遍历对象p>
<ul>
<li v-for="(val, key, index) in objList" :key="key">
{{ index }} - {{ key }} - {{ val.title }}
li>
ul>
div>
template>
<script>
export default {
data() {
return {
flag: false,
arrList: [
{ id: '1', title: 'title1' },
{ id: '2', title: 'title2' },
{ id: '3', title: 'title3' }
],
objList: {
a: { title: 'title1' },
b: { title: 'title2' },
c: { title: 'title3' }
}
}
}
}
script>
<style scoped>
style>
<template>
<div>
<p>{{ num }}p>
<button @click="handleClickIncre1">+1button>
<button @click="handleClickIncre2(2, $event)">+2button>
<a @click.stop="doSomeThing">a>
<form @submit.prevent="onSubmit">form>
<a @click.stop.prevent="doSomeThing">a>
<form @submit.prevent>form>
<div @click.capture="doSomeThing">div>
<div @click.self="doSomeThing">div>
<button @click.ctrl="onClick">Abutton>
<button @click.ctrl.exact="onClick">Abutton>
<button @click.exact="onClick">Abutton>
div>
template>
<script>
export default {
data() {
return {
num: 0
}
},
methods: {
handleClickIncre1(event) {
// 原生的 event 对象
console.log('event', event, event.__proto__.constructor) // event PointerEvent {...} PointerEvent() { [native code] }
console.log(event.target) //
console.log(event.currentTarget) // 事件是被注册到当前元素的
this.num ++
},
handleClickIncre2(val, event) {
console.log(event.target) //
this.num = this.num + val
}
}
}
script>
<style scoped>
style>
<template>
<div>
<p>输入框:{{ name }}p>
<input type="text" v-model.trim="name" />
<input type="text" v-model.lazy="name" />
<input type="text" v-model.number="age" />
<p>多行文本:{{ desc }}p>
<textarea v-model="desc">textarea>
<p>复选框 {{ checked }}p>
<input type="checkbox" v-model="checked" />
<p>多个复选框 {{ checkedNames }}p>
<input type="checkbox" id="jae" value="Jae" v-model="checkedNames" />
<label for="jae">Jaelabel>
<input type="checkbox" id="tom" value="Tom" v-model="checkedNames" />
<label for="tom">Tomlabel>
<input type="checkbox" id="amy" value="Amy" v-model="checkedNames" />
<label for="amy">Amylabel>
<p>单选 {{ gender }}p>
<input type="radio" id="male" value="male" v-model="gender" />
<label for="male">男label>
<input type="radio" id="female" value="female" v-model="gender" />
<label for="female">女label>
<p>下拉列表选择 {{ selected }}p>
<select v-model="selected">
<option disabled value="">请选择option>
<option>Aoption>
<option>Boption>
<option>Coption>
select>
<p>下拉列表多选 {{ selectedList }}p>
<select v-model="selectedList" multiple>
<option disabled value="">请选择option>
<option>Aoption>
<option>Boption>
<option>Coption>
select>
div>
template>
<script>
export default {
data() {
return {
name: 'Jae',
age: 22,
desc: 'hello',
checked: true,
checkedNames: [],
gender: 'male',
selected: '',
selectedList: []
}
}
}
script>
<style scoped>
style>
代码示例:
<template>
<div>
<Input @add="addHandler" />
<List :list="list" @delete="deleteHandler" />
div>
template>
<script>
import Input from './input'
import List from './List'
export default {
name: 'ComponentsDemo',
components: {
Input,
List
},
data() {
return {
list: [
{
id: 'id-1',
title: '标题1'
}
]
}
},
methods: {
addHandler(title) {
this.list.push({
id: `id-${Date.now()}`,
title
})
},
deleteHandler(id) {
console.log(1);
this.list = this.list.filter(item => item.id !== id)
}
}
}
script>
<template>
<div>
<input type="text" v-model="title">
<button @click="addTitle">addbutton>
div>
template>
<script>
export default {
name: 'InputName',
data() {
return {
title: ''
}
},
methods: {
addTitle() {
this.$emit('add', this.title)
this.title = ''
}
}
}
script>
<template>
<div>
<ul>
<li v-for="item in list" :key="item.id">
{{ item.title }}
<button @click="deleteItem(item.id)">删除button>
li>
ul>
div>
template>
<script>
export default {
name: 'ListName',
props: {
list: {
type: Array,
default: () => []
}
},
data() {
return {}
},
methods: {
deleteItem(id) {
this.$emit('delete', id)
}
}
}
script>
// event.js
import Vue from 'vue'
export default new Vue()
<script>
import event from './event'
export default {
name: 'InputName',
data() {
return {
title: ''
}
},
methods: {
addTitle() {
event.$emit('inputAddTitle', this.title)
}
}
}
script>
<script>
import event from './event'
export default {
mounted() {
event.$on('inputAddTitle', this.addTitleHandler)
},
beforeDestroy() {
// 及时销毁,否则可能造成内存泄漏
event.$off('inputAddTitle', this.addTitleHandler)
},
methods: {
addTitleHandler(title) {
console.log('input组件emit过来的:', title)
}
}
}
script>
1)单个组件
<!-- index.vue -->
created() {
console.log('index.vue created')
},
mounted() {
console.log('index.vue mounted')
}
<!-- List.vue -->
created() {
console.log('List.vue created')
},
mounted() {
console.log('List.vue mounted')
}
输出为:
index.vue created
List.vue created
List.vue mounted
index.vue mounted
即:父组件比子组件先创建,但是父组件要等子组件渲染完才能渲染
<template>
<div>
<p>{{ text }}p>
<CustomVModel v-model="text" />
div>
template>
<script>
import CustomVModel from './CustomVModel.vue'
export default {
name: 'AdvancedUse',
components: {
CustomVModel
},
data() {
return {
text: 'Jae'
}
}
}
script>
<template>
<div>
<input type="text" :value="text" @input="$emit('change', $event.target.value)">
div>
template>
<script>
export default {
model: {
prop: 'text', // 对应 props 中的 text
event: 'change'
},
props: {
text: {
type: String,
default: ''
}
}
}
script>
代码示例:
<template>
<div>
<ul ref="ul">
<li v-for="(item, index) in list" :key="index">{{ item }}li>
ul>
<button @click="add">添加button>
div>
template>
<script>
export default {
name: 'NextTick',
data() {
return {
list: [1, 2, 3]
}
},
methods: {
add() {
this.list.push(`${Date.now()}`)
this.list.push(`${Date.now()}`)
this.list.push(`${Date.now()}`)
const ulEle = this.$refs.ul // 获取 DOM 元素
console.log(ulEle.childNodes.length)
}
}
}
script>
可以看出这个输出结果不太对,一开始是3个,点击添加后添加了3个,怎么输出长度还是3呢?这就是因为此时输出的 DOM 节点还是上一次的,还未更新,如果需要得到正常的结果,就需要加上 $nextTick
确保 DOM 渲染完成:
this.$nextTick(() => {
const ulEle = this.$refs.ul
console.log(ulEle.childNodes.length)
})
代码示例:
<template>
<div>
<SlotDemo :url="website.url">
{{ website.title }}
SlotDemo>
div>
template>
<script>
import SlotDemo from './SlotDemo.vue'
export default {
name: 'AdvancedUse',
components: {
SlotDemo
},
data() {
return {
website: {
url: 'https://www.bing.com',
title: '搜索引擎',
subTitle: '比百度好用的搜索引擎'
}
}
}
}
script>
<template>
<div>
<a :href="url">
<slot>
默认内容,即父组件没设置内容时,显示的东西
slot>
a>
div>
template>
<script>
export default {
name: 'SlotDemo',
props: {
url: {
type: String,
defalut: ''
}
},
data() {
return {}
}
}
script>
如果将 index.vue 中 SlotDemo 组件修改一下:
<SlotDemo :url="website.url" />
代码示例:
<template>
<div>
<ScopedSlotDemo :url="website.url">
ScopedSlotDemo>
div>
template>
<script>
import ScopedSlotDemo from './ScopedSlotDemo.vue'
export default {
name: 'AdvancedUse',
components: {
ScopedSlotDemo
},
data() {
return {}
}
}
script>
<template>
<div>
<a :href="url">
<slot :slotData="website">
{{ website.subTitle }}
slot>
a>
div>
template>
<script>
export default {
props: {
url: {
type: String,
defalut: ''
}
},
data() {
return {
website: {
url: 'https://www.baidu.com',
title: '某搜索引擎',
subTitle: '比bing不好用的搜索引擎'
}
}
}
}
script>
在父组件中的插槽接收即可:
<template>
<div>
<ScopedSlotDemo :url="website.url">
<template v-slot="{ slotData }">
{{ slotData.title }}
template>
ScopedSlotDemo>
div>
template>
<script>
import ScopedSlotDemo from './ScopedSlotDemo.vue'
export default {
name: 'AdvancedUse',
components: {
ScopedSlotDemo
},
data() {
return {
website: {
url: 'https://www.bing.com',
title: '搜索引擎',
subTitle: '比百度好用的搜索引擎'
}
}
}
}
script>
<div>
<header>
<slot name="header">slot>
header>
<main>
<slot>slot>
main>
<footer>
<slot name="footer">slot>
footer>
div>
<NamedSlot>
<template #header>
<h1>将插入 header slot 中h1>
template>
<p>将插入 main slot 中,即默认的未命名的 slotp>
<template #header>
<h2>将插入 footer slot 中h2>
template>
NamedSlot>
:is="componentName"
用法<template>
<div>
<component :is="componentName" />
div>
template>
<script>
import NextTick from './NextTick.vue'
export default {
name: 'AdvancedUse',
components: {
NextTick
},
data() {
return {
componentName: 'NextTick'
}
}
}
script>
<template>
<div>
<NextTick v-if="showCom" />
<button @click="showCom = true">show Componentbutton>
div>
template>
<script>
// import NextTick from './NextTick.vue' 不要同步引进来
export default {
name: 'AdvancedUse',
components: {
NextTick: () => import ('../components/NextTick') // 动态引入
},
data() {
return {
showCom: false
}
}
}
script>
<template>
<div>
<button @click="changeState('A')">Abutton>
<button @click="changeState('B')">Bbutton>
<button @click="changeState('C')">Cbutton>
<keepAliveStateA v-if="state === 'A'" />
<keepAliveStateB v-if="state === 'B'" />
<keepAliveStateC v-if="state === 'C'" />
div>
template>
<script>
import keepAliveStateA from './keepAliveStateA'
import keepAliveStateB from './keepAliveStateB'
import keepAliveStateC from './keepAliveStateC'
export default {
name: 'KeepAlive',
components: {
keepAliveStateA,
keepAliveStateB,
keepAliveStateC
},
data() {
return {
state: 'A'
}
},
methods: {
changeState(state) {
this.state = state
}
}
}
script>
<template>
<div>state Adiv>
template>
<script>
export default {
data() {
return {}
},
computed: {},
watch: {},
created() {},
mounted() {
console.log('A mounted')
},
destroyed() {
console.log('A destroyed')
},
}
script>
<template>
<div>state Bdiv>
template>
<script>
export default {
data() {
return {}
},
computed: {},
watch: {},
created() {},
mounted() {
console.log('B mounted')
},
destroyed() {
console.log('B destroyed')
},
}
script>
<template>
<div>state Cdiv>
template>
<script>
export default {
data() {
return {}
},
computed: {},
watch: {},
created() {},
mounted() {
console.log('C mounted')
},
destroyed() {
console.log('C destroyed')
},
}
script>
如果不需要每次切换的时候都销毁组件,该怎么做呢?使用 keep-alive
:
<template>
<div>
<button @click="changeState('A')">Abutton>
<button @click="changeState('B')">Bbutton>
<button @click="changeState('C')">Cbutton>
<keep-alive>
<keepAliveStateA v-if="state === 'A'" />
<keepAliveStateB v-if="state === 'B'" />
<keepAliveStateC v-if="state === 'C'" />
keep-alive>
div>
template>
script>
<template>
<div>
<p>{{ name }} {{ age }} {{ city }}p>
<button @click="showName">显示姓名button>
div>
template>
<script>
import myMixin from './mixin'
export default {
mixins: [myMixin], // 可添加多个
data() {
return {
name: 'Jae',
age: 22
}
},
mounted() {
console.log('index mounted')
},
}
script>
// mixin.js
export default {
data() {
return {
city: 'XXX'
}
},
mounted() {
console.log('mixin mounted')
},
methods: {
showName() {
console.log(this.name)
}
}
}
const router = new VueRouter({
routes: [
// 动态路径参数,以冒号开头
{ path: '/user/:id', component: User }
]
})
export default new VueRouter({
routes: [
{
path: '/',
component: () => import('./../components/home')
}
]
})