概念:Vue.js 允许你自定义过滤器,可被用作一些常见的文本格式化。过滤器可以用在两个地方:mustache 插值和 v-bind 表达式。过滤器应该被添加在 JavaScript 表达式的尾部,由“管道”符指示;
https://cn.vuejs.org/v2/guide/filters.html#ad
| 第一个命令的输出作为第二个命令的输入过滤器可以用在两个地方:双花括号插值和 v-bind 表达式
<!-- 在双花括号中 -->{{ message | capitalize }}<!-- 在 `v-bind` 中 --><div v-bind:id="rawId | formatId"></div>
全局过滤器的定义
// 过滤器的定义语法Vue.filter('过滤器的名称', function(){})// 过滤器中的 function ,第一个参数,已经被规定死了,永远都是 过滤器 管道符前面 传递过来的数据Vue.filter('过滤器的名称', (data)=>{return data + '123';})
过滤器的使用示例
<div id="app"><!-- 格式化为年月日 --><p>{{ new Date() | dateFormat() }}</p><!-- 给金额前加上¥货币符号 --><p>{{ 399 | moneyFormat }}</p><p>{{ 399 | moneyFormat('$')}}</p><!-- 敏感词过滤 将其中单纯替换为** --><p>{{ '曾经,我也是一个单纯的少年,单纯的我,傻傻的问,谁是世界上最单纯的男人!' | msgFormat('--') }}</p></div>
Vue.filter定义全局过滤器
// 时间过滤器Vue.filter('dateFormat', (data) => {const date = new Date(data)// 获取年月日const year = date.getFullYear()const month = date.getMonth()const day = date.getDate()return `${year} 年 ${month} 月 ${day} 日`});// 金额过滤器Vue.filter('moneyFormat',(data,sign="¥")=>{return sign+data;});// 过滤单纯敏感词Vue.filter('msgFormat', function(data, arg = "***") {return data.replace(/单纯/g, arg);});

HTML元素:
<div id="app"><p>{{ new Date() | dataFormat}}</p> <!-- 2021-05-05 18:26:25 --><p>{{ new Date() | dataFormat('yyyy-mm-dd')}}</p> <!-- 2021-05-05 --></div>
私有过滤器 filters 定义方式:
// 全局过滤器Vue.filter('dateFormat', (data) => {const date = new Date(data)// 获取年月日const year = date.getFullYear()const month = date.getMonth()const day = date.getDate()return `${year} 年 ${month} 月 ${day} 日~~`});var vm = new Vue({el: '#app',data: {},methods: {},filters: { // 私有局部过滤器,只能在 当前 VM 对象所控制的 View 区域进行使用dataFormat(data, pattern = "") { // 在参数列表中 通过 pattern="" 来指定形参默认值,防止报错var dt = new Date(data);// 获取年月日var y = dt.getFullYear();var m = (dt.getMonth() + 1).toString().padStart(2, '0');var d = dt.getDate().toString().padStart(2, '0');// 如果 传递进来的字符串类型,转为小写之后,等于 yyyy-mm-dd,那么就返回 年-月-日// 否则,就返回 年-月-日 时:分:秒if (pattern.toLowerCase() === 'yyyy-mm-dd') {return `${y}-${m}-${d}`;} else {// 获取时分秒var hh = dt.getHours().toString().padStart(2, '0');var mm = dt.getMinutes().toString().padStart(2, '0');var ss = dt.getSeconds().toString().padStart(2, '0');return `${y}-${m}-${d} ${hh}:${mm}:${ss}`;}}}});// 使用ES6中的字符串新方法 String.prototype.padStart(maxLength, fillString='') 或 String.prototype.padEnd(maxLength, fillString='')来填充字符串长度;
注意:当有局部和全局两个名称相同的过滤器时候,会以就近原则进行调用,即:局部过滤器优先于全局过滤器被调用!
过滤器可以串联多个,前一个过滤器的返回值作为后一个的参数
给定一个状态 status ,值为 1、2、3
1:待付款 2:待发货 3:待收货
分别设置:红色、灰色、绿色
<style>.no-pay {background-color: #ccc;padding: 10px;}.no-shipments {background-color: orange;padding: 10px;}.yes-shipments {background-color: green;padding: 10px;}.take-delivery {background-color: red;padding: 10px;}</style><div id="app"><span v-bind:class="1 | getStatus | setStatusColor">{{ 1 | getStatus }}</span><span v-bind:class="2 | getStatus | setStatusColor">{{ 2 | getStatus }}</span><span v-bind:class="3 | getStatus | setStatusColor">{{ 3 | getStatus }}</span><span v-bind:class="4 | getStatus | setStatusColor">{{ 4 | getStatus }}</span></div>
filters定义局部过滤器
filters: {// 判断是什么状态getStatus(data) {switch(data) {case 1:return '待付款'case 2:return '待发货'case 3:return '已发货'case 4:return '待收货'}},// 设置状态文字颜色setStatusColor(data) {switch(data) {case '待付款':return 'no-pay'case '待发货':return 'no-shipments'case '已发货':return 'yes-shipments'case '待收货':return 'take-delivery'}}}

官方文档地址:https://cn.vuejs.org/v2/guide/custom-directive.html
使用directive定义全局的指令,directives定义局部的指令。其中在定义的时候,指令的名称前不需要加v-前缀。
// 使用 Vue.directive() 定义全局的指令 v-focus// 其中:参数1 : 指令的名称,注意,在定义的时候,指令的名称前面,不需要加 v- 前缀,// 但是: 在调用的时候,必须 在指令名称前 加上 v- 前缀来进行调用// 参数2: 是一个对象,这个对象身上,有一些指令相关的函数,这些函数可以在特定的阶段,执行相关的操作Vue.directive('focus', {bind: function(el) { // 每当指令绑定到元素上的时候,会立即执行这个 bind 函数,只执行一次// 注意: 在每个 函数中,第一个参数,永远是 el ,表示 被绑定了指令的那个元素,这个 el 参数,是一个原生的JS对象// 在元素 刚绑定了指令的时候,还没有 插入到 DOM中去,这时候,调用 focus 方法没有作用// 因为,一个元素,只有插入DOM之后,才能获取焦点// el.focus()},inserted: function(el) { // inserted 表示元素 插入到DOM中的时候,会执行 inserted 函数【触发1次】el.focus()// 和JS行为有关的操作,最好在 inserted 中去执行},updated: function(el) { // 当VNode更新的时候,会执行 updated, 可能会触发多次}})// 自定义一个 设置字体颜色的 指令Vue.directive('color', {// 样式,只要通过指令绑定给了元素,不管这个元素有没有被插入到页面中去,这个元素肯定有了一个内联的样式// 将来元素肯定会显示到页面中,这时候,浏览器的渲染引擎必然会解析样式,应用给这个元素bind: function(el, binding) {// el.style.color = 'red'// console.log(binding.name)// 和样式相关的操作,一般都可以在 bind 执行// console.log(binding.value)// console.log(binding.expression)el.style.color = binding.value}})
// 自定义局部指令 v-color 和 v-font-weight,为绑定的元素设置指定的字体颜色 和 字体粗细:new Vue({el: '#app',data:{},methods:{},filters:{},directives: {focus: {// 指令的定义 当被绑定的元素插入到 DOM 中时……inserted: function (el) {el.focus()}},color: { // 为元素设置指定的字体颜色bind(el, binding) {el.style.color = binding.value;}},'font-weight': function (el, binding2) {// 自定义指令的简写形式,等同于定义了 bind 和 update 两个钩子函数el.style.fontWeight = binding2.value;}'fontsize': function(el,binding){el.style.fontSize = parseInt(binding.value) + 'px';}}});
在很多时候,你可能想在 bind 和 update 时触发相同行为,而不关心其它的钩子。比如这样写:
Vue.directive('color-swatch', function (el, binding) {el.style.backgroundColor = binding.value})
调用自定义指令时,需要在指令名称前加上v-前缀调用自定义指令。
<input type="text" v-model="searchName" v-focus v-color="'red'" v-font-weight="900" fontsize='36'>
一个指令定义对象可以提供如下几个钩子函数 (均为可选):
bind:只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置。inserted:被绑定元素插入父节点时调用 (仅保证父节点存在,但不一定已被插入文档中)。update:所在组件的 VNode 更新时调用,但是可能发生在其子 VNode 更新之前。指令的值可能发生了改变,也可能没有。但是你可以通过比较更新前后的值来忽略不必要的模板更新 (详细的钩子函数参数见下)。
componentUpdated:指令所在组件的 VNode 及其子 VNode 全部更新后调用。
unbind:只调用一次,指令与元素解绑时调用。指令钩子函数会被传入以下参数:
el:指令所绑定的元素,可以用来直接操作 DOM。binding:一个对象,包含以下 property:name:指令名,不包括 v- 前缀。value:指令的绑定值,例如:v-my-directive="1 + 1" 中,绑定值为 2。oldValue:指令绑定的前一个值,仅在 update 和 componentUpdated 钩子中可用。无论值是否改变都可用。expression:字符串形式的指令表达式。例如 v-my-directive="1 + 1" 中,表达式为 "1 + 1"。arg:传给指令的参数,可选。例如 v-my-directive:foo 中,参数为 "foo"。modifiers:一个包含修饰符的对象。例如:v-my-directive.foo.bar 中,修饰符对象为 { foo: true, bar: true }。vnode:Vue 编译生成的虚拟节点。移步 VNode API 来了解更多详情。oldVnode:上一个虚拟节点,仅在 update 和 componentUpdated 钩子中可用。
<div id="directive" v-demo:foo.a.b="message"></div>Vue.directive('demo', {bind: function (el, binding, vnode) {var s = JSON.stringifyel.innerHTML ='name: ' + s(binding.name) + '<br>' +'value: ' + s(binding.value) + '<br>' +'expression: ' + s(binding.expression) + '<br>' +'argument: ' + s(binding.arg) + '<br>' +'modifiers: ' + s(binding.modifiers) + '<br>' +'vnode keys: ' + Object.keys(vnode).join(', ')}});new Vue({el: '#directive',data: {message: 'hello!'}});
在监听键盘事件时,我们经常需要检查详细的按键。Vue 允许为 v-on 在监听键盘事件时添加按键修饰符:
<!-- 只有在 `key` 是 `Enter` 时调用 `vm.submit()` --><input v-on:keyup.enter="submit">
你可以直接将 KeyboardEvent.key 暴露的任意有效按键名转换为 kebab-case 来作为修饰符。
<input v-on:keyup.page-down="onPageDown">
在上述示例中,处理函数只会在 $event.key 等于 PageDown 时被调用。
Vue 提供了绝大多数常用的按键码的别名
.enter.tab.delete (捕获“删除”和“退格”键).esc.space.up.down.left.right使用按键码别名可以做到兼容:
有一些按键 (.esc以及所有的方向键) 在 IE9 中有不同的key值, 如果你想支持 IE9,这些内置的别名应该是首选。
Vue.directive('on').keyCodes.f2 = 113;
Vue.config.keyCodes.名称 = 按键值来自定义案件修饰符的别名:
Vue.config.keyCodes.f2 = 113;
<input type="text" v-model="name" @keyup.f2="add">

这张图对于Vue的生命周期和钩子函数说的非常的明白。下面我们看一张关于Vue生命周期中出现的钩子函数示意图。

Vue实例有一个完整的生命周期,也就是从开始创建、初始化数据、编译模板、挂载Dom、渲染→更新→渲染、销毁等一系列过程,我们称这是Vue的生命周期。通俗说就是Vue实例从创建到销毁的过程,就是生命周期。
Vue应用程序中有4个主要事件(8个主要钩子)。主要的生命周期函数分类:
<!DOCTYPE html><html><head><title>生命周期全过程</title><script type="text/javascript" src="https://cdn.jsdelivr.net/vue/2.1.3/vue.js"></script></head><body><div id="app"><p>{{ message }}</p></div><script type="text/javascript">var app = new Vue({el: '#app',data: {message : "hello world!"},beforeCreate: function () {console.group('beforeCreate 创建前状态===============》');console.log("%c%s", "color:red" , "el : " + this.$el); //undefinedconsole.log("%c%s", "color:red","data : " + this.$data); //undefinedconsole.log("%c%s", "color:red","message: " + this.message) //undefined},created: function () {console.group('created 创建完毕状态===============》');console.log("%c%s", "color:red","el : " + this.$el); //undefinedconsole.log("%c%s", "color:red","data : " + this.$data); //已被初始化console.log("%c%s", "color:red","message: " + this.message); //已被初始化},beforeMount: function () {console.group('beforeMount 挂载前状态===============》');console.log("%c%s", "color:red","el : " + (this.$el)); //已被初始化console.log(this.$el);console.log("%c%s", "color:red","data : " + this.$data); //已被初始化console.log("%c%s", "color:red","message: " + this.message); //已被初始化},mounted: function () {console.group('mounted 挂载结束状态===============》');console.log("%c%s", "color:red","el : " + this.$el); //已被初始化console.log(this.$el);console.log("%c%s", "color:red","data : " + this.$data); //已被初始化console.log("%c%s", "color:red","message: " + this.message); //已被初始化},beforeUpdate: function () {console.group('beforeUpdate 更新前状态===============》');console.log("%c%s", "color:red","el : " + this.$el);console.log(document.querySelector('#app').innerHTML);console.log("%c%s", "color:red","data : " + this.$data);console.log("%c%s", "color:red","message: " + this.message);},updated: function () {console.group('updated 更新完成状态===============》');console.log("%c%s", "color:red","el : " + this.$el);console.log(document.querySelector('#app').innerHTML);console.log("%c%s", "color:red","data : " + this.$data);console.log("%c%s", "color:red","message: " + this.message);},beforeDestroy: function () {console.group('beforeDestroy 销毁前状态===============》');console.log("%c%s", "color:red","el : " + this.$el);console.log(this.$el);console.log("%c%s", "color:red","data : " + this.$data);console.log("%c%s", "color:red","message: " + this.message);},destroyed: function () {console.group('destroyed 销毁完成状态===============》');console.log("%c%s", "color:red","el : " + this.$el);console.log(this.$el);console.log("%c%s", "color:red","data : " + this.$data);console.log("%c%s", "color:red","message: " + this.message)}})</script></body></html>

每一个组件或者实例都会经历一个完整的生命周期,总共分为三个阶段:初始化、运行中、销毁。
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>完整的生命周期</title></head><body><div id="app"><my-template></my-template></div><template id="myTemplate"><div><p class="myp">A组件</p><button @click="destroy">destroy</button><input type="text" v-model="msg"><p>msg:{{msg}}</p></div></template></body><script type="text/javascript" src="https://cdn.jsdelivr.net/vue/2.1.3/vue.js"></script><script>//生命周期:初始化阶段 运行中阶段 销毁阶段Vue.component("myTemplate",{template:"#myTemplate",data:function(){return {msg:'hello'}},timer:null,methods:{destroy:function(){this.$destroy(); // 断点 销毁组件}},beforeCreate:function(){console.group('beforeCreate 创建前状态===============》');console.log('beforeCreate:刚刚new Vue()之后,这个时候,数据还没有挂载呢,只是一个空壳')console.log(this.msg)//undefinedconsole.log(document.getElementsByClassName("myp")[0])//undefined},created:function(){console.group('created 创建完毕状态===============》');console.log('created:这个时候已经可以使用到数据,也可以更改数据,在这里更改数据不会触发updated函数')this.msg+='!!!'console.log('在这里可以在渲染前倒数第二次更改数据的机会,不会触发其他的钩子函数,一般可以在这里做初始数据的获取')console.log('接下来开始找实例或者组件对应的模板,编译模板为虚拟dom放入到render函数中准备渲染')},beforeMount:function(){console.group('beforeMount 挂载前状态===============》');console.log('beforeMount:虚拟dom已经创建完成,马上就要渲染,在这里也可以更改数据,不会触发updated')this.msg+='@@@@';console.log('在这里可以在渲染前最后一次更改数据的机会,不会触发其他的钩子函数,一般可以在这里做初始数据的获取')console.log(document.getElementsByClassName("myp")[0])//undefinedconsole.log('接下来开始render,渲染出真实dom')},// render:function(createElement){// console.log('render')// return createElement('div','hahaha')// },mounted:function(){console.group('beforeMount 挂载结束状态===============》');console.log('mounted:此时,组件已经出现在页面中,数据、真实dom都已经处理好了,事件都已经挂载好了')console.log(document.getElementsByClassName("myp")[0])console.log('可以在这里操作真实dom等事情...')// this.$options.timer = setInterval(function () {// console.log('setInterval')// this.msg+='!'// }.bind(this),500)},beforeUpdate:function(){console.group('updated 更新前状态===============》');//这里不能更改数据,否则会陷入死循环console.log('beforeUpdate:重新渲染之前触发')console.log('然后vue的虚拟dom机制会重新构建虚拟dom与上一次的虚拟dom树利用diff算法进行对比之后重新渲染')},updated:function(){console.group('updated 更新完成状态===============》');//这里不能更改数据,否则会陷入死循环console.log('updated:数据已经更改完成,dom也重新render完成')},beforeDestroy:function(){console.group('destroyed 销毁前状态===============》');console.log('beforeDestory:销毁前执行($destroy方法被调用的时候就会执行),一般在这里善后:清除计时器、清除非指令绑定的事件等等...')// clearInterval(this.$options.timer)},destroyed:function(){console.group('destroyed 销毁完成状态===============》');console.log('destroyed:组件的数据绑定、监听...都去掉了,只剩下dom空壳,这里也可以善后')}})const vm = new Vue({}).$mount('#app')</script></html>

这么多钩子函数,我们怎么用呢,我想大家可能有这样的疑问吧,我也有,哈哈哈。
为什么要有动画:动画能够提高用户的体验,帮助用户更好的理解页面中的功能;
<div id="app"><input type="button" value="动起来" @click="myAnimate"><!-- 使用 transition 将需要过渡的元素包裹起来 --><transition name="fade"><div v-show="isshow">动画哦</div></transition></div>
// 创建 Vue 实例,得到 ViewModelvar vm = new Vue({el: '#app',data: {isshow: false},methods: {myAnimate() {this.isshow = !this.isshow;}}});
/* 定义进入和离开时候的过渡状态 */.fade-enter-active,.fade-leave-active {transition: all 0.2s ease;position: absolute;}/* 定义进入过渡的开始状态 和 离开过渡的结束状态 */.fade-enter,.fade-leave-to {opacity: 0;transform: translateX(100px);}
<link rel="stylesheet" type="text/css" href="./lib/animate.css">
<transitionenter-active-class="fadeInRight"leave-active-class="fadeOutRight":duration="{ enter: 500, leave: 800 }"><div class="animated" v-show="isshow">动画哦</div></transition>
<div id="app"><input type="button" value="切换动画" @click="isshow = !isshow"><transition@before-enter="beforeEnter"@enter="enter"@after-enter="afterEnter"><div v-if="isshow" class="show">OK</div></transition></div>
methods: {beforeEnter(el) { // 动画进入之前的回调el.style.transform = 'translateX(500px)';},enter(el, done) { // 动画进入完成时候的回调el.offsetWidth;el.style.transform = 'translateX(0px)';done();},afterEnter(el) { // 动画进入完成之后的回调this.isshow = !this.isshow;}}
.show{transition: all 0.4s ease;}
<style>.list-enter,.list-leave-to {opacity: 0;transform: translateY(10px);}.list-enter-active,.list-leave-active {transition: all 0.3s ease;}</style>
<div id="app"><input type="text" v-model="txt" @keyup.enter="add"><transition-group tag="ul" name="list"><li v-for="(item, i) in list" :key="i">{{item}}</li></transition-group></div>
// 创建 Vue 实例,得到 ViewModelvar vm = new Vue({el: '#app',data: {txt: '',list: [1, 2, 3, 4]},methods: {add() {this.list.push(this.txt);this.txt = '';}}});
<transition-group> 组件还有一个特殊之处。不仅可以进入和离开动画,还可以改变定位。要使用这个新功能只需了解新增的 v-move 特性,它会在元素的改变定位的过程中应用。
v-move 和 v-leave-active 结合使用,能够让列表的过渡更加平缓柔和:
.v-move{transition: all 0.8s ease;}.v-leave-active{position: absolute;}
什么是组件: 组件的出现,就是为了拆分Vue实例的代码量的,能够让我们以不同的组件,来划分不同的功能模块,将来我们需要什么样的功能,就可以去调用对应的组件即可;
组件化和模块化的不同:
<html>一样
var com1 = Vue.extend({template: '<h2>第一种方式</h2>',data(){return{}}});Vue.component('mycom1', com1);
Vue.component('mycom2', {template: '<h4>第一种方式的最终简写</h4>',data(){return {}}});
<script id="tmpl" type="template"><div><a href="#">{{msg.login}}</a> | <a href="#">{{msg.register}}</a></div></script>
Vue.component('account', {template: '#tmpl',data(){return{msg: {login: '登录',register: '注册'}}}});
<template>中定义 HTML 结构
<template id="tmp"><div><h2>第二种方式</h2><h3 v-text="msg"></h3></div></template>
使用 Vue.component 中 template 属性 进行调用
Vue.component('myCom3', {template: '#tmp',data(){return{msg: '好耶~'}}});
new Vue({el: '#app',data: {},methods:{},filters:{},directives:{},components: {myLogin: {template: `<div><h1>login 组件</h1><p>私有组件</p></div>`,data(){return{}}}},beforeCreate(){},created(){},beforeMount(){},Mounted(){},beforeUpdate(){},updated(){},beforeDestroy(){},destroyed(){}});
注意: 组件中的DOM结构,有且只能有唯一的根元素(Root Element)来进行包裹!
分离私有组件的定义,将组件模板对象分开定义
const myLogin = {template: `<div><h1>login 组件</h1><p>私有组件</p></div>`,data(){return{}}}new Vue({el: '#app',data: {},methods:{},components: {// 组件名称:组件的模板对象// myLogin: myLoginmyLogin,}});
我们的子组件是可以多级嵌套的,子组件中还可以在声明子组件。
<div id="app"><account></account></div><script>// 创建 Vue 实例,得到 ViewModelvar vm = new Vue({el: '#app',data: {},methods: {},components: {account: {template: `<div><h1>这是Account组件{{name}}</h1><login></login><register></register></div>`,data(){return {name: 'hello world!'}},components: {login: {template: "<h3>这是登录组件</h3>"},register: {template: '<h3>这是注册组件</h3>'}}}}});</script>
<div id="app"><mycom1></mycom1><mycom2></mycom2><my-com3></my-com3><my-login></my-login></div>
因为组件需要被重用,为了让每个组件有自己的私有作用域,data需要为函数并且返回一个对象
在组件中,data需要被定义为一个方法
通过计数器案例演示
<div id="app"><myCount></myCount><hr><myCount></myCount><hr><myCount></myCount><hr></div><template id="tmp"><input type="button" value="+1" @click="increment"><h3 v-text="count"></h3></template><script>Vue.component('myCount',{template: '#tmp',data: function (){return {count: 0}},methods:{increment(){this.count++;}}});new Vue({el:'#app',data:{ },methods:{ }})</script>
<div id="app"><a href="" @click.prevent="flag = true">登录</a><a href="" @click.prevent="flag = false">注册</a><transition mode="out-in"><login v-if="flag"></login><register v-else="flag"></register></transition></div><script>Vue.component('login',{template: '<h3>登录组件</h3>'})Vue.component('register',{template: '<h3>注册组件</h3>'})new Vue({el: '#app',data:{flag: true,},methods:{}})</script>
<component>进行切换:is 指定要显示的组件名称
<style>.v-enter,.v-leave-to {opacity: 0;transform: translateX(150px);}.v-enter-active,.v-leave-active {transition: all .5s ease;}</style><div id="app"><a href="" @click.prevent="comName = 'login'">登录</a><a href="" @click.prevent="comName = 'register'">注册</a><a href="" @click.prevent="comName = 'forget'">忘记密码</a><!-- 通过mode属性,设置组件切换时候的模式 --><transition mode="out-in"><component :is="comName"></component></transition></div><script>Vue.component('login',{template: '<h3>登录组件</h3>'})Vue.component('register',{template: '<h3>注册组件</h3>'})Vue.component('forget',{template: '<h3>忘记密码组件</h3>'})new Vue({el: '#app',data:{comName: 'login'},methods:{}})</script>
注意:一定要使用props属性来定义父组件传递过来的数据,由于 props 默认是单向绑定,即父组件的属性发生改变,子组件也会改变。反之则不会。props中数据是只读的
使用v-bind或简化指令:,将数据传递到子组件中
<div id="app"><!-- 父组件可以在引用子组件的时候,通过属性绑定的形式 ,把需要传递给子组件的数据,以属性绑定的形式传递到子组件内部供使用--><my-component v-bind:parentmsg="msg" :msg="message"></my-component></div><script>Vue.component('myComponent', {template: '<span>{{ parentmsg }}--{{msg}}</span>',// props:声明待接收的父组件数据// props中数据都是只读的,无法重新赋值props: ['parentmsg', 'msg'],// 把父组件传递过来的parentmsg和msg属性,现在props数组中定义一下,这样才能使用父组件传递过来的数据data() {return {// 子组件中也可以有自己的数据在data中}}})var vm = new Vue({el: '#app',data: {msg: 'hello 子组件',message: 'hello world'}})</script>
<div id="app"><!-- 默认 单向绑定 --><my-component :msg="message"></my-component><!-- 双向绑定 --><my-component :msg.sync="message"></my-component><!-- 单向绑定 --><my-component :msg.once="message"></my-component></div>
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}}}})
getMsg是父组件中methods中定义的方法名称,func是子组件调用传递过来方法时候的方法名称
<son v-on:func="show"></son>
this.$emit('方法名', 要传递的数据)方式,来调用父组件中的方法,同时把数据传递给父组件使用
<div id="app"><h1>{{msg}}</h1><!-- 父组件向子组件传递方法,使用的是事件绑定机制 --><!-- v-on,当我们自定义了一个事件属性之后,那么子组件就能够通过某种方式来调用 --><son @func="getMsg"></son></div><!-- 组件模板定义 --><template id="son"><div><h1>这是子组件</h1><input type="button" value="向父组件传值" @click="sendMsg" /></div></template><script>const son = {template: '#son', // 组件模板Iddata(){return {msg: "我是子组件传递过来的数据"}},methods: {sendMsg() { // 按钮的点击事件// 我们可以通过调用父组件传递过来的方法,将子组件数据通过参数形式传递给父组件中this.$emit('func', this.msg); // 调用父组件传递过来的方法,同时把数据传递出去}}}// 子组件的定义方式Vue.component('son',son);// 创建 Vue 实例,得到 ViewModelvar vm = new Vue({el: '#app',data: {msg: "父组件"},methods: {getMsg(val){ // 子组件中,通过 this.$emit() 实际调用的方法,在此进行定义this.msg = val;console.log("调用了父组件身上的getMsg方法");alert(val);}}});</script>
ref属性,然后赋予一个优雅的名字
<h3 ref="myh3">我是H3</h3><!-- login组件 --><login ref="login"></login>
$refs来获取DOM
getElement() { console.log(this.$refs.myh3); console.log(this.$refs.login.$el.innerText);}
<style>.pagination {display: flex;list-style: none;}.page-item {width: 25px;height: 25px;line-height: 25px;text-align: center;border: 1px solid #ccc;}.page-item.active {background-color: skyblue;}</style><div id="app"><page-component :total="total"></page-component></div><template id="page-component"><ul class="pagination"><li :class="p == page ? 'page-item active' : 'page-item'" v-for="p in pagecount"><a href="#" class="page-link" @click.prevent="page = p">{{ p }}</a></li></ul></template><script>const pageComponent = {template: '#page-component',name: 'PageComponent',props: ['total'],data: function() {return {page: 1, // 当前页码pagesize: 10 // 每页显示条数}},computed: {pagecount: function() {// 总页码数return Math.ceil(this.total / this.pagesize)}}}var vm = new Vue({el: '#app',data: {total: 35},components: {pageComponent}})</script>
<div id="app"><div v-for="goods in goodslist"><p>商品名称:{{ goods.name }}</p><p>单价:{{ goods.price }}</p><cart-component v-model="goods.count"></cart-component><hr></div><div>订单总金额:{{ amount }} 元</div></div><template id="cart-component"><div class="cart"><button @click="count--; updateCount();">-</button><input type="text" v-model="count" style="width: 50%;" @input="updateCount()"><button @click="count++; updateCount();">+</button></div></template><script>const cartComponent = {name: 'Cart',template: '#cart-component',// 在组件中不允许直接修改 props 中的数据props: ['value'],data: function() {return {count: this.value}},methods: {// v-model 指令双向数据绑定,修改父组件内容updateCount: function() {// 触发 input 事件this.$emit('input', this.count)}}}const app = new Vue({el: '#app',data: {goodslist: [{name: 'iphone 8 plus',price: 5888,count: 0},{name: 'iphone x',price: 7222,count: 0}]},computed: {// 当前订单总金额amount: function() {var money = 0;this.goodslist.forEach(goods => {money += parseInt(goods.count) * parseInt(goods.price)})return money;}},components: {cartComponent}})</script>
<div id="app"><cmt-box @loadcomments="loadComments"></cmt-box><ul class="list-group"><li class="list-group-item" v-for="item in list" :key="item.id"><span class="badge">评论人:{{item.user}}</span> {{item.content}}</li></ul></div><template id="temp"><div><div class="form-group"><label for="">评论人:</label><input type="text" class="form-control" v-model="user"></div><div class="form-group"><label for="">评论内容:</label><textarea class="form-control" v-model="content"></textarea></div><div class="form-group"><input type="button" value="发表评论" @click="postComment"></div></div></template><script>const vm = new Vue({el: '#app',data: {list: []},methods: {loadComments() {const list = JSON.parse(localStorage.getItem('cmts') || '[]');this.list = list;console.log(6666);}},created() {this.loadComments();},components: {'cmt-box': {template: '#temp',data() {return {user: '',content: ''}},methods: {postComment() {const comment = {id: Date.now(),user: this.user,content: this.content};// 从localStorage中获取所有的评论const list = JSON.parse(localStorage.getItem('cmts') || '[]');list.unshift(comment);// 保存最新的评论数据localStorage.setItem('cmts', JSON.stringify(list));this.user = this.content = '';this.$emit('loadcomments');}},}}});</script>
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号