vue|vue入门--js高阶函数(箭头函数)、v-model数据绑定、组件化、父子组件通信及访问

vue入门–基础命令+axios+案例练习 vue入门–vue常用属性、生命周期、计算属性、过滤器、组件、虚拟DOM、数组的响应式方法、页面闪烁、ES6简单语法增强 vue入门–js高阶函数(箭头函数)、v-model数据绑定、组件化、父子组件通信及访问 JavaScript高阶函数 在说javascript高阶函数之前,有这样一个案例,有一个对象数组,我要计算数组中所有对象的总金额问题。

let books = [{ id: 1, name: "《算法导论》", date: "2006-9", price: 85.12, count: 2 }, { id: 2, name: "《UNIX编程艺术》", date: "2006-2", price: 59.28, count: 1 }, { id: 3, name: "《编程珠玑》", date: "2008-10", price: 39.2, count: 1 } ]

【vue|vue入门--js高阶函数(箭头函数)、v-model数据绑定、组件化、父子组件通信及访问】普通方法: 普通for循环/for in /for of
let total=0 // 普通for循环 for (let i = 0; i < books.length; i++) { total += books[i].count*books[i].price; } return total; -------------------------------------------------------------------------- // for in实际上和 普通for循环一样 for (let i in books) { // i 是下标 total += books[i].count*books[i].price; } return total; -------------------------------------------------------------------------- // for of一般循环遍历,尽量优先使用 for of for (const book of books) { // i 是元素 total += book.count*book.price; } return total;

每次计算都需要循环遍历,代码写起来很麻烦,有没有一种函数,直接给我把值全都计算好呢。当然有,和java stream的reduce规约操作一样,js一样有reduce规约操作。
reduce–高阶函数之规约操作 语法:
reduce(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: number[]) => number, initialValue: number)

可以看到,这个方法中需要两个参数:
  • 回调函数(必填)
    • previousValue(必填):上一次计算的结果值(注意:当没有设置初始值时,第一次执行时,数组中的第一个元素将会作为计算结果)
    • currentValue(必填):当前元素
    • 非必填的可以去查阅详细资料
  • 初始值(非必填)
    一般情况下是不需要设置初始值的,但是如果是对象类型的数组,你会发现这个初始值设计的巧妙。
普通数组
先看下普通的数组,求数组中所有数据之和,因为是普通值类型数组,一般情况下只传入一个回调函数就完全够用,previousValue会被当成初始值;如果有初始值要求设置上就行了
普通回调函数
let arrs = [10, 20, 30, 111, 500,34] function arrsReduce(){ return arrs.reduce(function(preValue, n){ return preValue + n; }) }

箭头函数回调
let arrs = [10, 20, 30, 111, 500,34] function arrsReduce(){ return arrs.reduce((preValue, n) => preValue + n); }

对象数组
还使用上面说到的计算数组中所有对象的总金额问题。
箭头函数回调
function finalTotal(){ return books.reduce((preValue, n) => prevalue + n.count*n.price, 0); }

会发现,上面用遍历写了一大堆,结果这边用一个规约操作,直接一行代码全搞定。
当对对象数组进行规约操作计算某总值时,一定要注意preValuen分别代表什么,如上preValue是上一次计算出的总额,那么preValue必须是number类型的。而n是一个对象类型,一定要知道。
那么刚开始执行时,preValue不能是第一个元素,只能是初始值0。
filter–高阶函数之过滤操作 filter回调函数中有一个要求:必须要返回一个boolean值
返回true时,函数内部会将这次回调的参数加入到新的数组中,false则被过滤掉
普通回调函数
let arrs = [10, 20, 30, 111, 500,34] function arrFilter(){ return arrs.filter(function(n){ // 每次遍历将数组中的元素一个个赋值给 n return n > 100 // 当返回值为 true,会把当前的n加入到新的数组中 }); }

箭头函数回调
不明白箭头函数的可以查下资料学习下,这里简单复习下
当函数中参数只有一个时,()可以省略不写;当函数体内语句只有一句时 {} 可以不写,并且return也可以不写。
let arrs = [10, 20, 30, 111, 500,34] function arrFilter(){ return arrs.filter(x => x > 100); }

map–高阶函数之映射操作 可单独对数组中每个元素进行操作,比如每个元素都 *2等,最后会生成新的数组
普通函数回调
let arrs = [10, 20, 30, 111, 500,34] function arrMap(){ return arrs.map(function(n){ return n * 2 }); }

箭头函数回调
let arrs = [10, 20, 30, 111, 500,34] function arrMap(){ return arrs.map(n => n*2); }

v-model text 双向绑定,数据和视图的绑定
{{message}}
> const app = new Vue({ el:"#app", data:{ message:"你好" } })

radio 使用v-model绑定同一个属性后,name可以省略(分组)
{{sex}}
src="https://www.it610.com/article/vue/vue.js"> > const app = new Vue({ el:"#app", data:{ sex: '女' } })

checkbox
你选择的是{{isAgree}} 篮球 足球 乒乓球 您的爱好是{{hobby}}
src="https://www.it610.com/article/vue/vue.js"> > const app = new Vue({ el:"#app", data:{ isAgree: false, hobby: [] } })

select
name="abc" id="" v-model="fruit"> {{fruit}}name="abc"v-model="fruits" multiple> {{fruits}}
src="https://www.it610.com/article/vue/vue.js"> > const app = new Vue({ el:"#app", data:{ fruit: '香蕉', fruits: [] } })

vue|vue入门--js高阶函数(箭头函数)、v-model数据绑定、组件化、父子组件通信及访问
文章图片

修饰符
  • .lazy : 绑定的属性懒加载,只有失去焦点或者用户输入回车时才去加载
  • .number : 表示绑定的值是number类型
  • .trim : 自动去除两端空格
组件化 就是将一个大的整体,拆分成一个个的小整体的组件。
基本使用
// 调用组件
src="https://www.it610.com/article/vue/vue.js"> > Vue.component('my-cpn', { // params1: 组件名称 template: `// params2: 定义模板标题 ` }) const app = new Vue({ el:"#app" })

全局组件和局部组件
// 此写法为全局组件,其他的vue对象中,也可以使用 Vue.component('my-cpn', { template: `标题 ` }) const app = new Vue({ el:"#app" })------------------------------------------------------- // 此写法为局部组件,只有在一个vue实例中,可以使用 const app = new Vue({ el:"#app", components:{ cpn:{ //组件名是 cpn template: `标题 ` } } })

组件模板抽离写法
src="https://www.it610.com/article/vue/vue.js"> > const app = new Vue({ el:"#app", components:{ cpn:{ template: "#cpn" // 将模板和组件绑定起来 } } })

请注意:template标签中必须有且只有一个root级的标签,否则会报错。
以上 中只写了一句,如果有多个元素,请一定要使用 或其他元素将它们包裹起来,如下:

组件中的数据存放问题 问题:组件中能否访问vue实例中的数据
组件如果想要访问vue实例中的数据,不能直接去访问,需要通过模板进行参数的传递。同vue实例中的data属性一样,组件也可以有存储数据的地方,但是与vue实例不同的是,组件中的data只能是一个函数,而不能是一个属性
src="https://www.it610.com/article/vue/vue.js"> > const app = new Vue({ el:"#app", components:{ cpn:{ template: "#cpn",// 组件中定义一个 data函数,用于返回数据 data(){ return { // 返回一个数据为对象类型 title: "标题" } } } } })

问题:为什么组件中的data必须是函数
可以从vue组件的实例化角度考虑,一个vue组件如果实例化多次,那么我们会想多个实例化对象是相互独立,互不影响的,data设置为函数,然后data函数中每次返回一个新的对象。那么vue组件多个实例使用的都不是同一个data的对象,自然就实现了多实例之间数据的互不影响。
父子组件及通信 每个组件中都有 components属性,如果要套子组件,那么直接在组件的 components中继续加组件即可。其实vue实例也可以看成为一个组件。
要注意:父子组件不可以跨级调用,除非在全局组件作用域中。
通信两种方式:
  • props:通过props向子组件传送数据
  • 通过事件向父组件发送消息 $emit
vue|vue入门--js高阶函数(箭头函数)、v-model数据绑定、组件化、父子组件通信及访问
文章图片

props : 父向子传递数据
props可以是一个数组,也可以是一个对象(可加数据类型验证等等)推荐使用
src="https://www.it610.com/article/vue/vue.js"> > const cpn ={ template: "#cpn", // props:['cmovies', 'cmessage']// props可以是一个数组,记得加 '' props:{ cmovies: Array, //可以进行数据类型验证 cmessage: {// 可设置对象 type: String,// 类型 default: 'aaa'// 默认值 } } } const app = new Vue({ el:"#app", data:{ movies:["海王", "加勒比海盗", "海尔兄弟"], message: "hello" }, components:{ cpn// es6增强写法,当k和v同名时,可以省略只写一个 } })

如果是Object或者Array类型,那么很可能高版本的vue不支持此写法
props:{ cmovies:{ type: Array, default: [] } }

提示报错,Invalid default value for prop: .. Props with type Object/Array must use a factory function to return the default value
写法改为:
props:{ cmovies: { type: Array, default(){ return [] } } }

写法总结图:
vue|vue入门--js高阶函数(箭头函数)、v-model数据绑定、组件化、父子组件通信及访问
文章图片

props中驼峰标识
假如我定义的props中有驼峰式写法
props:{ cInfo:{ type: Object, default(){ return {} } } }


$emit子组件向父组件发消息(自定义事件)
src="https://www.it610.com/article/vue/vue.js"> > const cpn = { template: "#cpn", data(){ return { categories: [ {id: 'aaa',name: "热门推荐"}, {id: 'bbb',name: "手机数码"}, {id: 'ccc',name: "家用家电"}, {id: 'ddd',name: "电脑办公"} ] } }, methods:{ btnClick(cate){ this.$emit("cateclick", cate)// (自定义一个事件)发送事件,cate是参数 } } } const app = new Vue({ el:"#app", components:{ cpn }, methods:{ cpnClick(cate){// 用来接收 子组件传给的参数 console.log(cate) } } });

结合v-model实现父子通信
:value + @input实现 首先要知道,v-model的实现其实就是:value绑定和@input传入来完成的
实现需求:
子组件中有一个输入框,需要把输入框中输入和数据及时更新到父组件的属性中,由于子组件中如果v-model来绑定props,vue不支持这种写法,所以我们要绑定子组件中的 data函数中的参数,并且当输入框输入数据后,通过自定义事件将值传递给父组件。
由于涉及到输入(事件)、展示(属性),所以不使用v-model进行绑定,而是使用底层的:value@input来配合完成。一般来讲,这种需求比较难遇到。
src="https://www.it610.com/article/vue/vue.js"> > const cpn = { template:"#cpn", props:{ number1: Number, number2: Number }, data(){ return{ dnumber1: this.number1, dnumber2: this.number2 } }, methods:{ num1change(event){ // 这里会默认把浏览器的事件传过来 this.dnumber1 = event.target.value; this.$emit('num1change', this.dnumber1) }, num2change(event){ this.dnumber2 = event.target.value; this.$emit('num2change', this.dnumber2) } } } const vue = new Vue({ el:"#app", data:{ num1: 1, num2: 2 }, components:{ cpn }, methods:{ num1change(value){ this.num1 = parseInt(value) }, num2change(value){ this.num2 = parseInt(value) } } })

watch监听实现 在子组件中定义watch监听
watch:{ dnumber1(newValue){ // 函数名就是 属性名,然后参数是 (新值[,旧值]),旧值非必填 this.dnumber1 = newValue; this.$emit('num1change', this.dnumber1) } }

父访问子&子访问父
  • 父访问子 : $children或者 $refs
  • 子访问父 : $parent
父访问子 父访问子:使用 $children(不推荐使用)
$children是获取到子组件的数组。数组中是所有的子组件,形成一个树形结构。
src="https://www.it610.com/article/vue/vue.js"> > const cpn = { template:"#cpn", methods: { // 方法 showMessage(){ // 子组件中定义方法 console.log("showMessage") } } } const app = new Vue({ el:"#app", components:{ cpn }, methods: { btnClick(){ console.log(this.$children); // 使用 $children获取所有子组件的集合,然后可以调用子组件中的属性或者是方法 this.$children[0].showMessage(); // 调用第一个子组件的 方法 } } })

vue|vue入门--js高阶函数(箭头函数)、v-model数据绑定、组件化、父子组件通信及访问
文章图片

父访问子: 使用 $refs (推荐使用)
直接根据ref能拿到子组件对象,注意是对象,不是集合
src="https://www.it610.com/article/vue/vue.js"> > const cpn = { template:"#cpn", methods: { showMessage(){ console.log("showMessage") } } } const app = new Vue({ el:"#app", components:{ cpn }, methods: { btnClick(){ console.log(this.$refs.aaa); this.$refs.aaa.showMessage(); } } })

子访问父 要注意层级关系,当父组件是 Vue实例的时候,那么父组件的类型就是一个 Vue类型,如果是父组件还是一个组件类型,那么父组件的类型就是 VueComponet。注意:获取到的是对象,不是数组
$parent,不推荐使用
由于会打乱结构,与组件独立这一观念冲突,一般不会去使用 $parent,更多是使用 $root直接获取vue实例对象。($parent就不再演示)
$root,直接获取vue实例
src="https://www.it610.com/article/vue/vue.js"> > const cpn = { template:"#cpn", methods: { btnClick(){ // 访问父组件 console.log(this.$root); console.log(this.$root.message) } } } const app = new Vue({ el:"#app", data:{ message: "你好" }, components:{ cpn } })

vue入门–基础命令+axios+案例练习 vue入门–vue常用属性、生命周期、计算属性、过滤器、组件、虚拟DOM、数组的响应式方法、页面闪烁、ES6简单语法增强 vue入门–js高阶函数(箭头函数)、v-model数据绑定、组件化、父子组件通信及访问

    推荐阅读