文章目录
Vue
一、组件的定义及复用性,局部组件和全局组件
<script>
// 组件的定义
// 组件具备复用性
// 全局组件,只要定义了,处处可以使用,性能不高,但是使用起来简单,名字建议 小写字母单词,中间用横线间隔
// 局部组件,定义了,要注册之后才能使用,性能比较高,使用起来有些麻烦,建议大些字母开头,驼峰命名
// 局部组件使用时,要做一个名字和组件间的映射对象,你不写映射,Vue 底层也会自动尝试帮你做映射
const Counter = {
data() {
return {
count: 1
}
},
template: `<div @click="count += 1">{{count}}</div>`
}
const HelloWorld = {
template: `<div>hello world</div>`
}
const app = Vue.createApp({
components: {
// counter: Counter,
// 'hello-world': HelloWorld,
Counter, HelloWorld,
},
template: `
<div>
<hello-world />
<counter />
</div>
`
});
// app.component('counter-parent', {
// template: `<counter />`
// })
// app.component('counter', {
// data() {
// return {
// count: 1
// }
// },
// template: `<div @click="count += 1">{{count}}</div>`
// })
const vm = app.mount('#root');
</script>
二、组件间传值及传值校验
动态传参 v-bind,静态传参。
<script>
const app = Vue.createApp({
data() {
return { num: 1234 }
},
template: `
<div><test :content="num" /></div>
`
});
// type:String, Boolean, Array, Object, Function, Symbol
// required 必填
// default 默认值
app.component('test', {
props: {
content: {
type: Number,
validator: function(value) {
return value < 1000;
},
default: function() {
return 456;
}
}
},
template: `<div>{{content}}</div>`
});
const vm = app.mount('#root');
</script>
三、单项数据流的理解
<script>
// v-bind="params"
// :content="params.content" :a="params.a" :b="params.b" :c="params.c"
// 属性传的时候,使用 content-abc 这种命名,接的时候,使用 contentAbc 命名
// 单项数据流的概念: 子组件可以使用父组件传递过来的数据,但是绝对不能修改传递过来的数据
const app = Vue.createApp({
data() {
return { num: 1 }
},
template: `
<div>
<counter :count="num" />
<counter :count="num" />
<counter :count="num" />
</div>
`
});
app.component('counter', {
props: ['count'],
template: `<div @click="count += 1">{{count}}</div>`
});
const vm = app.mount('#root');
</script>
四、Non-Props属性
<script>
// Non-prop 属性
const app = Vue.createApp({
template: `
<div>
<counter msg="hello" msg1="hello1" />
</div>
`
});
app.component('counter', {
// inheritAttrs: false,
mounted() {
console.log(this.$attrs.msg);
},
template: `
<div :msg="$attrs.msg">Counter</div>
<div v-bind="$attrs">Counter</div>
<div :msg1="$attrs.msg1">Counter</div>
`
});
const vm = app.mount('#root');
</script>
五、父子组件间如何通过事件进行通信
<script>
const app = Vue.createApp({
data() {
return { count: 1 }
},
template: `
<counter v-model="count" />
`
});
app.component('counter', {
props: ['modelValue'],
methods: {
handleClick() {
this.$emit('update:modelValue', this.modelValue + 3);
}
},
template: `
<div @click="handleClick">{{modelValue}}</div>
`
});
const vm = app.mount('#root');
</script>
六、组件间双向绑定
<script>
const app = Vue.createApp({
data() {
return {
count: 'a',
}
},
template: `
<counter v-model.uppercase="count" />
`
});
app.component('counter', {
props: {
'modelValue': String,
'modelModifiers': {
default: ()=> ({})
}
},
methods: {
handleClick() {
let newValue = this.modelValue + 'b';
if(this.modelModifiers.uppercase) {
newValue = newValue.toUpperCase();
}
this.$emit('update:modelValue', newValue);
},
},
template: `
<div @click="handleClick">{{modelValue}}</div>
`
});
const vm = app.mount('#root');
</script>
七、使用插槽和具名插槽解决组件内容传递问题
<script>
// slot 插槽
// slot 中使用的数据,作用域的问题
// 父模版里调用的数据属性,使用的都是父模版里的数据
// 子模版里调用的数据属性,使用的都是子模版里的数据
// 具名插槽
const app = Vue.createApp({
template: `
<layout>
<template v-slot:header>
<div>header</div>
</template>
<template v-slot:footer>
<div>footer</div>
</template>
</layout>
`
});
app.component('layout', {
template: `
<div>
<slot name="header"></slot>
<div>content</div>
<slot name="footer"></slot>
</div>
`
});
const vm = app.mount('#root');
</script>
八、作用域插槽
<script>
// 作用域插槽
const app = Vue.createApp({
template: `
<list v-slot="{item}">
<div>{{item}}</div>
</list>
`
});
app.component('list', {
data() {return {list: [1, 2, 3]}},
template: `
<div>
<slot v-for="item in list" :item="item" />
</div>
`
});
const vm = app.mount('#root');
</script>
九、动态组件和异步组件
<script>
// 动态组件: 根据数据的变化,结合 compoent 这个标签,来随时动态切换组件的现实
// 异步组件: 是异步执行某些组件的逻辑,这叫做异步组件
const app = Vue.createApp({
template: `
<div>
<common-item />
<async-common-item />
</div>
`
});
app.component('common-item', {
template: `<div>hello world</div>`
});
app.component('async-common-item', Vue.defineAsyncComponent(() => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve({
template: `<div>this is an async component</div>`
})
}, 4000)
})
}))
const vm = app.mount('#root');
</script>
十、基础语法-补
<script>
// v-once 让某个元素标签只渲染一次
// ref 实际上是获取 Dom 节点 / 组件引用 的一个语法
// provide / inject
const app = Vue.createApp({
data() {
return { count: 1}
},
provide() {
return {
count: this.count,
}
},
template: `
<div>
<child :count="count" />
<button @click="count += 1">Add</button>
</div>
`
});
app.component('child', {
template: `<child-child />`
});
app.component('child-child', {
inject: ['count'],
template: `<div>{{count}}</div>`
});
const vm = app.mount('#root');
</script>
十一、使用Vue实现基础的CSS过渡与动画效果
<style>
/* 动画
@keyframes leftToRight {
0% {
transform: translateX(-100px);
}
50% {
transform: translateX(-50px);
}
0% {
transform: translateX(0px);
}
}
.animation {
animation: leftToRight 3s;
} */
/* 过渡
.transition {
transition: 3s background-color ease;
}
.blue {
background: blue;
}
.green {
background: green;
} */
.transition {
transition: 3s background-color ease;
}
</style>
<script src="https://unpkg.com/vue@next"></script>
</head>
<body>
<div id="root"></div>
</body>
<script>
const app = Vue.createApp({
data() {
return {
styleObj: {
background: 'blue'
}
}
},
methods: {
handleClick() {
if(this.styleObj.background === 'blue') {
this.styleObj.background = 'green';
}else {
this.styleObj.background = 'blue'
}
}
},
template: `
<div>
<div class="transition" :style="styleObj">hello world</div>
<button @click="handleClick">切换</button>
</div>
`
});
const vm = app.mount('#root');
</script>
十二、使用transition标签实现单元素组件的过渡和动画效果
<style>
@keyframes shake {
0% {
transform: translateX(-100px)
}
50% {
transform: translateX(-50px)
}
100% {
transform: translateX(50px)
}
}
.hello-leave-active {
animation: shake 3s;
}
.hello-enter-active {
animation: shake 3s;
}
</style>
<script src="https://unpkg.com/vue@next"></script>
</head>
<body>
<div id="root"></div>
</body>
<script>
// 单元素,单组件的入场出场动画
const app = Vue.createApp({
data() {
return {
show: false
}
},
methods: {
handleClick() {
this.show = !this.show;
}
},
template: `
<div>
<transition name="hello">
<div v-if="show">hello world</div>
</transition>
<button @click="handleClick">切换</button>
</div>
`
});
const vm = app.mount('#root');
</script>
<script src="https://unpkg.com/vue@next"></script>
</head>
<body>
<div id="root"></div>
</body>
<script>
// 单元素,单组件的入场出场动画
const app = Vue.createApp({
data() {
return {
show: false
}
},
methods: {
handleClick() {
this.show = !this.show;
},
handleBeforeEnter(el) {
el.style.color = "red";
},
handleEnterActive(el, done) {
const animation = setInterval(() => {
const color = el.style.color;
if(color === 'red') {
el.style.color = 'green';
} else {
el.style.color = 'red';
}
}, 1000)
setTimeout(() => {
clearInterval(animation);
done();
}, 3000)
},
handleEnterEnd(el) {
alert(123);
}
},
template: `
<div>
<transition
:css="false"
@before-enter="handleBeforeEnter"
@enter="handleEnterActive"
@after-enter="handleEnterEnd"
>
<div v-show="show">hello world</div>
</transition>
<button @click="handleClick">切换</button>
</div>
`
});
const vm = app.mount('#root');
</script>
十三、组件和元素切换动画的实现
<link
rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.1.1/animate.min.css"
/>
<title>lesson 25</title>
<style>
.v-leave-to {
opacity: 0;
}
.v-enter-from {
opacity: 0;
}
.v-enter-active,
.v-leave-active {
transition: opacity 1s ease-in;
}
.v-leave-from ,
.v-enter-to {
opacity: 1;
}
</style>
<script src="https://unpkg.com/vue@next"></script>
</head>
<body>
<div id="root"></div>
</body>
<script>
// 多个单元素标签之间的切换
// 多个单组件之间的切换
const ComponentA = {
template: '<div>hello world</div>'
}
const ComponentB = {
template: '<div>bye world</div>'
}
const app = Vue.createApp({
data() {
return { component: 'component-a' }
},
methods: {
handleClick() {
if(this.component === 'component-a') {
this.component = 'component-b';
}else {
this.component = 'component-a';
}
},
},
components: {
'component-a': ComponentA,
'component-b': ComponentB,
},
template: `
<div>
<transition mode="out-in" appear>
<component :is="component" />
</transition>
<button @click="handleClick">切换</button>
</div>
`
});
const vm = app.mount('#root');
</script>
十四、状态动画
<script>
// 状态动画
const app = Vue.createApp({
data() {
return {
number: 1,
animateNumber: 1
}
},
methods: {
handleClick() {
this.number = 10;
if(this.animateNumber < this.number) {
const animation = setInterval(() => {
this.animateNumber += 1;
if(this.animateNumber === 10) {
clearInterval(animation);
}
}, 100);
}
},
},
template: `
<div>
<div>{{animateNumber}}</div>
<button @click="handleClick">增加</button>
</div>
`
});
const vm = app.mount('#root');
</script>