全局指令
<body>
<div id="app">
<h2 v-color>自定义指令</h2>
<h2 v-color="'blue'">自定义指令</h2>
<div v-format-time>2021-10-20 14:57:19</div>
<div v-format-time="'YYYY-MM-DD'">2021-10-20 14:57:19</div>
<div v-format-time="'YYYY-MM-DD HH:mm:ss'">2021-10-20 14:57:19</div>
<input type="text" v-focus>
</div>
<script src="./lib/vue.js"></script>
<script>
// 定义的时候不添加前缀
Vue.directive('color', {
bind(el, binding) {
console.log(binding)
// 在 内存中操作 操作样式
// console.log(el)
el.style.color = binding.value || 'red'
},
inserted() {
// 页面已经渲染完毕了
},
updated() {
}
})
Vue.directive('focus', {
bind(el) {
// 在 内存中操作
// console.log(el)
},
inserted(el) {
// 页面已经渲染完毕了 操作DOM
el.focus()
},
updated() {
}
})
Vue.directive('format-time', {
inserted(el, binding) {
el.textContent = moment(el.textContent).format(binding.value || 'YYYY-MM-DD')
}
})
new Vue({
el: "#app",
data: {
},
created() {
},
methods: {
}
})
</script>
</body>
私有指令
<body>
<div id="app">
<h2 v-color>自定义指令</h2>
<h2 v-color="'blue'">自定义指令</h2>
<div v-format-time>2021-10-20 14:57:19</div>
<div v-format-time="'YYYY-MM-DD'">2021-10-20 14:57:19</div>
<div v-format-time="'YYYY-MM-DD HH:mm:ss'">2021-10-20 14:57:19</div>
<input type="text" v-focus>
</div>
<div id="app2">
<h2 v-color>自定义指令</h2>
<h2 v-color="'blue'">自定义指令</h2>
<div v-format-time>2021-10-20 14:57:19</div>
<div v-format-time="'YYYY-MM-DD'">2021-10-20 14:57:19</div>
<div v-format-time="'YYYY-MM-DD HH:mm:ss'">2021-10-20 14:57:19</div>
<input type="text" v-focus>
</div>
<script src="./lib/vue.js"></script>
<script>
// 定义的时候不添加前缀
Vue.directive('color', {
bind(el, binding) {
console.log(binding)
// 在 内存中操作 操作样式
// console.log(el)
el.style.color = binding.value || 'red'
},
inserted() {
// 页面已经渲染完毕了
},
updated() {
}
})
Vue.directive('focus', {
bind(el) {
// 在 内存中操作
// console.log(el)
},
inserted(el) {
// 页面已经渲染完毕了 操作DOM
el.focus()
},
updated() {
}
})
Vue.directive('format-time', {
inserted(el, binding) {
el.textContent = moment(el.textContent).format(binding.value || 'YYYY-MM-DD')
}
})
new Vue({
el: "#app",
directives: {
// color: {
// bind(el, binding) {
// console.log(binding)
// el.style.color = binding.value || 'red'
// }
// },
// 简写方式自动 调用 bind 和 updated
color(el, binding) {
el.style.color = binding.value || 'red'
},
focus: {
inserted(el) {
// 页面已经渲染完毕了 操作DOM
el.focus()
}
},
'format-time': {
inserted(el, binding) {
el.textContent = moment(el.textContent).format(binding.value || 'YYYY-MM-DD')
}
}
}
})
new Vue({
el: "#app2"
})
// 全局的自定义指令可以使用在任意的实例
// 私有的自定义指令只可以使用在自己的实例,如果全局和私有同时存在 优先 就近原则 使用 私有的
</script>
过滤器
<body>
<div id="app">
<h2>{{msg}}</h2>
<h2>{{msg|msgfmt('快乐', '疯狂')}}</h2>
<div>{{ctime}}</div>
<div>{{ctime | datefmt}}</div>
<div :time="ctime| datefmt">
{{ctime}}
</div>
</div>
<script src="./lib/vue.js"></script>
<script>
Vue.filter('msgfmt', (arg, arg2, arg3) => {
console.log(arg)
return arg.replace(arg2, arg3)
})
// Vue.filter('datefmt', (arg) => {
// return moment(arg).format('YYYY-MM-DD HH:mm:ss')
// })
new Vue({
el: "#app",
data: {
msg: '学习使我快乐',
ctime: new Date().getTime()
},
created() {
},
methods: {
},
directives: {},
filters: {
datefmt(arg) {
return moment(arg).format('YYYY-MM-DD HH:mm:ss')
}
}
})
</script>
</body>
动画
<style>
/* 设置起点和终点的位置和状态 */
.v-enter,
.v-leave-to {
opacity: 0;
transform: translateX(300px);
}
/* 设置动画的时间 */
.v-enter-active {
transition: all 1s linear;
}
.v-leave-active {
transition: all .5s linear;
}
</style>
</head>
<body>
<div id="app">
<button @click="isShow=!isShow">toggle</button>
<transition>
<div v-show="isShow">
显示、隐藏
</div>
</transition>
</div>
<script src="./lib/vue.js"></script>
<script>
new Vue({
el: "#app",
data: {
isShow: false
}
})
</script>
</body>
<style>
/* 设置起点和终点的位置和状态 */
.v-enter,
.v-leave-to {
opacity: 0;
transform: translateX(300px);
}
/* 设置动画的时间 */
.v-enter-active {
transition: all 1s linear;
}
.v-leave-active {
transition: all .5s linear;
}
/* 设置起点和终点的位置和状态 */
.fly-enter,
.fly-leave-to {
opacity: 0;
transform: translateY(300px);
}
/* 设置动画的时间 */
.fly-enter-active {
transition: all 1s linear;
}
.fly-leave-active {
transition: all .5s linear;
}
</style>
</head>
<body>
<div id="app">
<button @click="isShow=!isShow">toggle</button>
<transition>
<div v-show="isShow">
显示、隐藏
</div>
</transition>
<button @click="isShow2=!isShow2">toggle</button>
<transition name="fly">
<div v-show="isShow2">
显示、隐藏
</div>
</transition>
</div>
<script src="./lib/vue.js"></script>
<script>
new Vue({
el: "#app",
data: {
isShow: false,
isShow2: false
}
})
</script>
</body>
第三方动画
<style>
/* 自定义css动画类 */
/* @keyframes bounce-in {
0% {
transform: scale(0);
}
50% {
transform: scale(1.5);
}
100% {
transform: scale(1);
}
}
.fly-enter-active {
animation: bounce-in 3s;
}
.fly-leave-active {
animation: bounce-in 3s reverse;
} */
</style>
</head>
<body>
<div id="app">
<button @click="isShow=!isShow">toggle</button>
<!--
name 设置动画的前缀
enter-active-class 设置进入的动画
leave-active-class 设置离开的动画 注意要设置我们基础类 animated
duration
duration="number" // 统一设置进入和离开的时间 number 0 到 1000 之间
:duration="obj"
:duration="{
enter: ,
leave:
}"
-->
<transition name="fly" enter-active-class="fadeInRight" leave-active-class="fadeOutRight"
:duration="{enter:500,leave:300}">
<div v-show="isShow" class="animated">
显示、隐藏
</div>
</transition>
</div>
<script src="./lib/vue.js"></script>
<script>
new Vue({
el: "#app",
data: {
isShow: false,
}
})
</script>
</body>
列表动画
<style>
.list-item {
display: inline-block;
margin-right: 10px;
}
.list-enter-active,
.list-leave-active {
transition: all 1s ease;
}
.list-enter,
.list-leave-to {
opacity: 0;
transform: translateY(30px);
}
.list-leave-active {
position: absolute;
}
/* 后续操作 */
.list-move {
transition: all 1s ease;
}
</style>
</head>
<body>
<div id="app">
<div id="list-demo" class="demo">
<button v-on:click="add">Add</button>
<button v-on:click="remove">Remove</button>
<!--
appear 页面一打开就有动画
列表动画使用 transition-group包含 这个标签默认为span ,可以通过tag设置为指定的标签
列表元素必须添加key
-->
<transition-group appear name="list" tag="p">
<span v-for="item in items" v-bind:key="item" class="list-item">
{{ item }}
</span>
</transition-group>
</div>
</div>
<script src="./lib/vue.js"></script>
<script>
new Vue({
el: "#app",
data: {
items: [1, 2, 3, 4, 5, 6, 7, 8, 9],
nextNum: 10
},
methods: {
randomIndex: function () {
return Math.floor(Math.random() * this.items.length)
},
add: function () {
this.items.splice(this.randomIndex(), 0, this.nextNum++)
},
remove: function () {
this.items.splice(this.randomIndex(), 1)
},
}
})
</script>
</body>
半场动画
<body>
<div id="app">
<input type="button" @click="toggle" value="toggle" :disabled="disabled">
<transition @before-enter="beforeEnter" @enter="enter" @after-enter="afterEnter">
<div v-show="isShow">
显示、隐藏
</div>
</transition>
</div>
<script src="./lib/vue.js"></script>
<script>
new Vue({
el: "#app",
data: {
isShow: false,
disabled: false
},
methods: {
beforeEnter(el) {
// console.log(el)
// 设置起点
el.style.transform = 'translate(0,0)'
},
enter(el, done) {
// true
// 强制刷新
el.offsetTop
el.style.transform = 'translate(300px,300px)'
el.style.transition = 'all 1s ease'
// done 是afterEnter 的回调函数
done()
},
afterEnter() {
// false
this.isShow = !this.isShow
},
toggle() {
this.isShow = !this.isShow
this.disabled = true
setTimeout(() => {
this.disabled = false
}, 1001)
}
}
})
// 动画的状态 false ---> true ---> false
</script>
</body>
组件
<body>
<div id="app">
<!-- 3. 渲染组件 -->
<my-header></my-header>
</div>
<script src="./lib/vue.js"></script>
<script>
// 1. 定义组件
// 组件定义首字母一般为大写
const MyHeader = {
template: `
<div>
<h2>logo</h2>
<div>
this is desction
</div>
</div>
`
}
// 2. 注册组件
// 单词首字母大写,但是当第二单词也大写的时候 使用 连接的方式渲染 如:MyHeader --- my-header
// 驼峰式命名 如:myHeader --- my-header
// 首字母大写 如:Login ---- Login 或者 login
Vue.component('MyHeader', MyHeader)
new Vue({
el: "#app"
})
</script>
</body>
组件内部模块抽离
<body>
<div id="app">
<!-- 3. 渲染组件 -->
<my-header></my-header>
</div>
<template id="template">
<!-- 模板中有且只能有一个根元素 -->
<div>
<h2>logo</h2>
<div>
this is desction
</div>
</div>
</template>
<script src="./lib/vue.js"></script>
<script>
const MyHeader = {
template: "#template"
}
Vue.component('MyHeader', MyHeader)
new Vue({
el: "#app"
})
</script>
</body>
私有组件
<body>
<div id="app">
<!-- 3. 渲染组件 -->
<my-header></my-header>
</div>
<div id="app2">
<!-- 3. 渲染组件 -->
<my-header></my-header>
</div>
<template id="template">
<!-- 模板中有且只能有一个根元素 -->
<div>
<h2>logo</h2>
<div>
this is desction
</div>
</div>
</template>
<script src="./lib/vue.js"></script>
<script>
const MyHeader = {
template: "#template"
}
// 全局组件 可以使用在任意的实例中
// Vue.component('MyHeader', MyHeader)
new Vue({
el: "#app",
// 私有组件只能使用在当前实例
components: {
MyHeader
}
})
new Vue({
el: '#app2'
})
</script>
</body>
动态组件
<body>
<div id="app">
<!-- 3. 渲染组件 -->
<my-header></my-header>
</div>
<div id="app2">
<!-- 3. 渲染组件 -->
<my-header></my-header>
</div>
<template id="template">
<!-- 模板中有且只能有一个根元素 -->
<div>
<h2>logo</h2>
<div>
this is desction
</div>
</div>
</template>
<script src="./lib/vue.js"></script>
<script>
const MyHeader = {
template: "#template"
}
// 全局组件 可以使用在任意的实例中
// Vue.component('MyHeader', MyHeader)
new Vue({
el: "#app",
// 私有组件只能使用在当前实例
components: {
MyHeader
}
})
new Vue({
el: '#app2'
})
</script>
</body>
异步组件
<body>
<div id="app">
<Login></Login>
<Register></Register>
<Foo></Foo>
</div>
<script src="./lib/vue.js"></script>
<script>
const Login = {
template: '<div> Login 组件</div>',
created() {
console.log('Login')
}
}
const Register = {
template: '<div> Register 组件</div>',
created() {
console.log('Register')
}
}
const Foo = {
template: '<div> Foo 组件</div>',
created() {
console.log('Foo')
}
}
new Vue({
el: "#app",
data: {
flag: true,
cName: 'Login'
},
components: {
// Login,
// Register,
// Foo
Login: function (resolve, reject) {
setTimeout(() => {
resolve(Login)
})
},
Register: function (resolve, reject) {
setTimeout(() => {
resolve(Register)
}, 500)
},
Foo: function (resolve, reject) {
setTimeout(() => {
resolve(Foo)
}, 1000)
}
}
})
</script>
</body>
组件动画
<style>
.fly-enter,
.fly-leave-to {
opacity: 0;
transform: translateX(300px);
}
.fly-enter-active,
.fly-leave-active {
transition: all 1s ease;
}
</style>
</head>
<body>
<div id="app">
<a href="###" @click="cName='Login'">Login</a>
<a href="###" @click="cName='Register'">Register</a>
<a href="###" @click="cName='Foo'">Foo</a>
<!-- mode 设置动画的模式 out-in in-out-->
<transition name="fly" mode="out-in">
<component :is="cName"></component>
</transition>
</div>
<script src="./lib/vue.js"></script>
<script>
const Login = {
template: '<div> Login 组件</div>'
}
const Register = {
template: '<div> Register 组件</div>'
}
const Foo = {
template: '<div> Foo 组件</div>'
}
new Vue({
el: "#app",
data: {
flag: true,
cName: 'Login'
},
components: {
Login,
Register,
Foo
}
})
</script>
</body>
匿名插槽
<body>
<!-- 插槽可以在父组件中修改子组件的界面,前提是子组件中提供了插槽 slot -->
<div id="app">
<Login>
</Login>
<Login>
<h2>login</h2>
<div>
desction
</div>
</Login>
</div>
<script src="./lib/vue.js"></script>
<script>
const Login = {
template: `
<div>
<slot>login</slot>
</div>
`
}
new Vue({
el: "#app",
data: {
},
created() {
},
methods: {
},
components: {
Login
}
})
</script>
</body>
具名插槽
<body>
<!-- 插槽可以在父组件中修改子组件的界面,前提是子组件中提供了插槽 slot -->
<div id="app">
<Login>
</Login>
<Login>
<!-- <template slot="logo"> -->
<mark slot="logo">logo</mark>
<!-- </template> -->
<template slot="des">
this is desction
</template>
</Login>
</div>
<script src="./lib/vue.js"></script>
<script>
const Login = {
// 具名插槽 ,可以根据名称修改指定的ui
template: `
<div>
<slot name="logo">logo</slot>
<slot name="des">des</slot>
<slot name="button">
<button>按钮</button>
</slot>
<slot></slot>
</div>
`
}
new Vue({
el: "#app",
components: {
Login
}
})
</script>
</body>
作用域插槽
<body>
<!-- 插槽可以在父组件中修改子组件的界面,前提是子组件中提供了插槽 slot -->
<div id="app">
<Login>
</Login>
<Login>
<!-- slot-scope 接收的是一个对象 可以通过解构语法简化 -->
<template slot-scope="{item}">
<strong v-if="item==='blue'">{{item}}</strong>
<span v-else>{{item}}</span>
</template>
</Login>
</div>
<script src="./lib/vue.js"></script>
<script>
const Login = {
data() {
return {
list: ['red', 'blue', 'green']
}
},
template: `
<div>
<p v-for="item in list">
<slot v-bind:item="item"> {{item}}</slot>
</p>
</div>
`
}
new Vue({
el: "#app",
components: {
Login
}
})
</script>
</body>
v-slot新写法
<body>
<div id="app">
<h2>2.5写法</h2>
<Login>
<template slot="header" slot-scope="scope">
this is header
{{scope.info}}
</template>
</Login>
<h2>2.6写法</h2>
<Login>
<template v-slot:header="scope">
this is header
{{scope.info}}
</template>
</Login>
<h2>2.6写法</h2>
<Login>
<template #header="scope">
this is header
{{scope.info}}
</template>
</Login>
</div>
<script src="./lib/vue.min.js"></script>
<script>
const Login = {
template: `
<div>
<slot v-bind:info="'子组件的数据'" name="header">header</slot>
</div>
`
}
new Vue({
el: "#app",
components: {
Login
}
})
</script>
</body>
父传子
<body>
<div id="app">
<h1>root----{{msg}}</h1>
<App></App>
<App :msg="msg"></App>
</div>
<script src="./lib/vue.js"></script>
<script>
const App = {
// props的数据是只读的,不要在子组件中修改父组件的数据
// props: ['msg'],
props: {
msg: {
type: String,
default: '默认值'
},
},
template: `
<div>
<h2>app----{{msg}}</h2>
<button @click="msg='更新了'">changeMsg</button>
</div>
`
}
new Vue({
el: "#app",
data: {
msg: '父组件的数据'
},
created() {
},
methods: {
},
components: {
App
}
})
</script>
</body>
子传父
<body>
<div id="app">
<h1>root----{{msg}}</h1>
<App :msg="msg" @click="getSonData"></App>
</div>
<script src="./lib/vue.js"></script>
<script>
const App = {
// props的数据是只读的,不要在子组件中修改父组件的数据
props: ['msg'],
template: `
<div>
<h2>app----{{msg}}</h2>
<button @click="setData">setData</button>
</div>
`,
methods: {
setData() {
this.$emit('click', '子组件的数据')
}
}
}
new Vue({
el: "#app",
data: {
msg: '父组件的数据'
},
methods: {
getSonData(data) {
this.msg = data
}
},
components: {
App
}
})
</script>
</body>
兄弟传值 事件总线
<body>
<div id="app">
<com-a></com-a>
<com-b></com-b>
</div>
<script src="./lib/vue.js"></script>
<script>
const eventBus = new Vue()
const ComA = {
template: `
<div>
ComA
</div>
`,
created() {
eventBus.$on('getdata', function (data) {
console.log(data)
})
}
}
const ComB = {
template: `
<div>
ComB
<button @click="setdata">setdata</button>
</div>
`,
methods: {
setdata() {
eventBus.$emit('getdata', 'b组件的值')
}
}
}
new Vue({
el: "#app",
data: {
},
created() {
},
methods: {
},
components: {
ComA,
ComB
}
})
</script>
</body>
refs
<body>
<div id="app">
<h1 ref="h1Ref" id="h1">root----{{msg}}</h1>
<App ref="appRef"></App>
</div>
<script src="./lib/vue.js"></script>
<script>
const App = {
data() {
return {
count: 1
}
},
props: {
msg: {
type: String,
default: '子组件'
}
},
template: `
<div>
<h2>app----{{msg}}</h2>
</div>
`,
methods: {
show() {
console.log('show')
}
}
}
new Vue({
el: "#app",
data: {
msg: '父组件的数据'
},
// 组件注册只会执行一次
created() {
// 实时监听DOM的变化
// this.$nextTick(() => {
// console.log(document.getElementById('h1'))
// console.log(this.$refs.h1Ref)
// console.log(this.$refs.appRef.count)
// this.$refs.appRef.show()
// })
},
// 组件注册只会执行一次
mounted() {
console.log(document.getElementById('h1'))
console.log(this.$refs.h1Ref)
console.log(this.$refs.appRef.count)
this.$refs.appRef.show()
},
methods: {
},
components: {
App
}
})
</script>
父传子 parent
<body>
<div id="app">
<h1>root----{{msg}}</h1>
<App></App>
</div>
<script src="./lib/vue.js"></script>
<script>
const App = {
props: {
msg: {
type: String,
default: '子组件'
}
},
template: `
<div>
<h2>app----{{msg}}</h2>
</div>
`,
created() {
console.log(this.$parent.msg)
this.$parent.show()
}
}
new Vue({
el: "#app",
data: {
msg: '父组件的数据'
},
methods: {
show() {
console.log(this.msg)
}
},
components: {
App
}
})
</script>
</body>
爷孙传值 listener
<body>
<div id="app">
<h1>root组件</h1>
<!-- 1. 在渲染的子组件上使用 v-bind 绑定传递 爷爷的数据 -->
<App :age="age" @show="show"></App>
</div>
<script src="./lib/vue.js"></script>
<script>
const Son = {
// 3. 在son组件中通过 $attrs 获取数据
template: `
<div>
<h3>son组件</h3>
爷爷的年龄:{{$attrs.age}}岁
<button @click="handleClick">handleClick</button>
</div>
`,
methods: {
handleClick() {
this.$emit('show')
}
}
}
const App = {
// 2. 在父组件中使用 v-bind="$attrs"
template: `
<div>
<h2>app组件</h2>
<Son v-bind="$attrs" v-on="$listeners"/>
</div>
`,
components: {
Son
},
created() {
console.log(this.$attrs)
}
}
new Vue({
el: "#app",
data: {
age: '90'
},
methods: {
show() {
console.log('root')
}
},
components: {
App
}
})
</script>
</body>
provide inject
<body>
<div id="app">
<h1>root----{{msg}}</h1>
<App></App>
</div>
<script src="./lib/vue.js"></script>
<script>
const Son = {
inject: ['name'],
props: {
msg: {
type: String,
default: '子组件'
}
},
template: `
<div>
<h3>son----{{msg}}</h3>
Son----{{name}}
</div>
`,
}
const App = {
// inject: {
// name: {
// }
// },
// inject: ['name'],
props: {
msg: {
type: String,
default: '子组件'
}
},
template: `
<div>
<h2>app----{{msg}}</h2>
<Son />
</div>
`,
components: {
Son
}
}
new Vue({
el: "#app",
data: {
msg: '父组件的数据'
},
provide: {
name: '顶层数据'
},
components: {
App
}
})
</script>
</body>