整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:

vue中的prop

vue中的prop

先为什么要引入prop这个东西,因为如果要向组件里面传递信息,在没有prop之前,是无法传递值到组件里面,因此引入了prop进行传递值。

1,Prop的大小写

官方文档,HTML对于attribute(属性)名的大小写是不敏感的,浏览器会把所有的大写字母,都解释为小写字母,因此使用DOM模板(就是原先写在html中,一打开就会被浏览器解析的代码)时,camelCase(驼峰命名法)的prop名需要使用等价的kebab-case( xx- xxx )命名:

Vue.component('blog-post', {
 // 在 JavaScript 中是 camelCase 的props: ['postTitle'],
 template: '<h3>{{ postTitle }}</h3>'})
<!-- 在 HTML 中是 kebab-case 的 -->
<blog-post post-title="hello!"></blog-post>

2,Prop类型

可以在定义prop时,指定值类型,如代码:

props: {
title: String,
likes: Number,
isPublished: Boolean,
commentIds: Array,
author: Object,
callback: Function,
contactsPromise: Promise // or any other constructor
}

3,传递静态或者动态的Prop

传入静态值:

<blog-posttitle="My journey with Vue"></blog-post>

传入动态值:

<!-- 动态赋予一个变量的值 -->
<blog-postv-bind:title="post.title">
</blog-post>
<!-- 动态赋予一个复杂表达式的值 -->
<blog-postv-bind:title="post.title + ' by ' + post.author.name"></blog-post>

传入数字

<!-- 即便 `42` 是静态的,我们仍然需要 `v-bind` 来告诉 Vue -->
<!-- 这是一个 JavaScript 表达式而不是一个字符串。-->
<blog-postv-bind:likes="42"></blog-post>
<!-- 用一个变量进行动态赋值。-->
<blog-postv-bind:likes="post.likes"></blog-post>
传入布尔值
<!-- 包含该 prop 没有值的情况在内,都意味着 `true`。-->
<blog-postis-published></blog-post>
<!-- 即便 `false` 是静态的,我们仍然需要 `v-bind` 来告诉 Vue -->
<!-- 这是一个 JavaScript 表达式而不是一个字符串。-->
<blog-postv-bind:is-published="false"></blog-post>
<!-- 用一个变量进行动态赋值。-->
<blog-postv-bind:is-published="post.isPublished"></blog-post>

传入数组

<!-- 即便数组是静态的,我们仍然需要 `v-bind` 来告诉 Vue -->
<!-- 这是一个 JavaScript 表达式而不是一个字符串。-->
<blog-postv-bind:comment-ids="[234, 266, 273]"></blog-post>
<!-- 用一个变量进行动态赋值。-->
<blog-postv-bind:comment-ids="post.commentIds"></blog-post>

传入一个对象

<!-- 即便对象是静态的,我们仍然需要 `v-bind` 来告诉 Vue -->
<!-- 这是一个 JavaScript 表达式而不是一个字符串。-->
<blog-postv-bind:author="{
 name: 'Veronica',
 company: 'Veridian Dynamics'
 }">
</blog-post> <!-- 用一个变量进行动态赋值。--> <blog-postv-bind:author="post.author"></blog-post>

传入一个对象中的所有property

一个对象post

post: {
 id: 1,
 title: 'My Journey with Vue'}

下面的模板:

<blog-postv-bind="post"></blog-post>

等价于:

<blog-postv-bind:id="post.id"v-bind:title="post.title"></blog-post>

4,单向数据流

所有的prop使得其父子prop之间形成了单向下行绑定,父级prop的更新会向下流动到子组件中,但是反过来是不行的。

在JavaScript中对象和数组是通过引用传入的,对于一个数组或者对象类型的prop来说,子组件中改变变更这个对象或者数组本身将会影响到父组件的状态。

5,Prop验证

为了实现验证prop,可以为prop中的值提供一个带有验证需求的对象。

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 } } } })

当prop验证失败的时候,vue会产生一个控制台警告。

类型检查时,type可以是原生构造函数的其中一个,比如

  • String
  • Number
  • Boolean
  • Array
  • Object
  • Date
  • Function
  • Symbol

也可以是自定义的构造函数

functionPerson(firstName, lastName) {
 this.firstName=firstName
 this.lastName=lastName
}

你可以使用:

Vue.component('blog-post', {
 props: {
 author: Person
 }
})

6,非Prop的Attribute

一个非prop的attribute是指传向一个组件,但该组件并没有想要的prop定义的attribute。

显示定义的prop适用于向一个子组件传入信息,然后组件库的作者并不总能预见组件会被用于怎样的场景。这也是组件为什么可以接受任意的attribute,而这些attribute会被添加到这个组件的根元素上。

例如,想象一下你通过一个 Bootstrap 插件使用了一个第三方的 <bootstrap-date-input> 组件,这个插件需要在其 <input> 上用到一个 data-date-picker attribute。我们可以将这个 attribute 添加到你的组件实例上:

<bootstrap-date-inputdata-date-picker="activated"></bootstrap-date-input>

然后这个 data-date-picker="activated" attribute 就会自动添加到 <bootstrap-date-input> 的根元素上。

替换/合并已有的attribute

如何组件中的class不同,会被合并起来,style也是如此。

想象一下 <bootstrap-date-input> 的模板是这样的:

<inputtype="date"class="form-control">

为了给我们的日期选择器插件定制一个主题,我们可能需要像这样添加一个特别的类名:

<bootstrap-date-inputdata-date-picker="activated"class="date-picker-theme-dark">
</bootstrap-date-input>

庆幸的是,classstyle attribute 会稍微智能一些,即两边的值会被合并起来,从而得到最终的值:form-control date-picker-theme-dark

禁用attribute继承

如果你希望组件的根元素继承 attribute,你可以在组件的选项中设置 inheritAttrs: false。例如:

rop

基本用法

Prop的基本用法很简单,只需要在子组件的Vue实例中定义该属性并把值设为目标属性的数组即可

Vue.component('child', {
 ...
 // 接收message
 props: ['message']
 ...
})

tips:由于HTML中的属性是不区分大小写的,所以当使用DOM中的模板(HTML中)时,驼峰写法需要转化为短横线写法。但是,如果使用字符串模板(JS中)时,不受限制,可以为所欲为。

Prop中的静态和动态值

在正常情况下,一般在父组件中通过v-bind定义一个动态值,子组件通过Prop接收该值,所以,很多人认为,Prop只能接收动态值。但是,其实Prop可以接受静态属性。

示例:

/* 父组件 */
<child type="video"></child>
 
/* 子组件 */
Vue.component('child', {
 ...
 // 成功接收
 props: ['type']
 ...
})

在示例中,父组件在子组件标签上定义了静态属性type,子组件依然通过Prop拿到了静态属性type。

单向数据流

所有的 prop 都使得其父子 prop 之间形成了一个单向下行绑定:父组件的 Prop 的更新会向下流动到子组件中,但是反过来则不行。这样会防止从子组件意外改变父组件以及同级子组件的状态,从而导致你的应用的数据流向难以理解。

另外,每次父组件发生更新时,子组件中所有的Prop都将刷新为最新的值。这意味着你不应该在子组件内部改变Prop,如果你这样做了,Vue会在控制台抛出一个警告。

一般来说,如果子组件需要操作Prop中的值,需要将Prop中的值赋值给本地定义的属性:

...
props: ['message'],
data () {
 return {
 mes: this.message
 }
}
...

非Prop特性

非Props特性是指在组件上定义了属性,而又没有使用Prop接受属性。此时,子组件内不可使用该属性值,该属性会直接添加到子组件的根节点上。

比如,在一个只含有一个div的子组件上,如果我向子组件传了一个content属性,但是子组件不使用Prop接收content属性,则渲染结果为:

<div id="root">
 <div content="hello"></div>
</div>

Prop校验

子组件用Props接收父组件传来的消息有多种形式:

1.数组形式

props: [data1, data2]

数组形式相当于直接接收消息,不做任何校验,一般来说,不太建议使用数组形式。

2.简单对象形式

props: {
 data1: String,
 data2: Array
}

简单对象形式对父组件传递的值进行了类型校验,如果传过来的值类型不一致,控制台会报错。

3.复杂对象形式

props: {
 data1: {
 type: String,
 required: true,
 default: 'default value',
 validator (value) {
 return (value.length < 5)
 }
 },
 data2: {
 type: Array,
 required: true,
 default: ()=> ['', '', '']
 }
}

复杂对象形式的情况下,作为对象属性的参数可以写为对象形式,参数对象含有4个属性,type、required、default、validator。

type:设定参数类型,当传入参数类型与type不相符时,控制台会报错

required:设定参数是否是必传,当设为true时,不传该参数会报错

default:设定默认值,当参数类型为复杂类型时,需使用工厂模式生成默认值,否则Vue会在控制台抛出警告。如图所示,就通过工厂模式生成了一个长度为3的空数组。

validator:校验器,是一个函数,拥有一个代表传入值的形参,可以自定义各种校验,当返回false时,会报错,表示没通过校验。

对前端的技术,架构技术感兴趣的同学关注我的头条号,并在后台私信发送关键字:“前端”即可获取免费的架构师学习资料

知识体系已整理好,欢迎免费领取。还有面试视频分享可以免费获取。关注我,可以获得没有的架构经验哦!!

比Python,JavaScript才是更适合写爬虫的语言。原因有如下三个方面:

  • JavaScript异步IO机制适用于爬虫这种IO密集型任务。JavaScript中的回调非常自然,使用异步网络请求能够充分利用CPU。
  • JavaScript中的jQuery毫无疑问是最强悍的HTML解析工具,使用JavaScript写爬虫能够减少学习负担和记忆负担。虽然Python中有PyQuery,但终究还是比不上jQuery自然。
  • 爬取结果多为JSON,JavaScript是最适合处理JSON的语言。

一、任务:爬取用户在Github上的repo信息

通过实例的方式学习爬虫是最好的方法,先定一个小目标:爬取github repo信息。入口URL如下,我们只需要一直点击next按钮就能够遍历到用户的所有repo。

https://github.com/{{username}}?tab=repositories

获取repo之后,可以做什么?

  • 统计用户最常使用的语言,统计用户语言使用分布情况统计用户所获取的star数,fork数

二、爬虫双股剑:axios和jQuery

axios是JavaScript中很常用的异步网络请求库,相比jQuery,它更轻量、更专业。既能够用于浏览器端,也可以用于Node。它的语法风格是promise形式的。在本任务中,只需要了解如下用法就足够了:

axios.get(url).then((resp)=> {
 请求成功,处理resp.data中的html数据
}).catch((err)=> {
 请求失败,错误处理
})

请求之后需要处理回复结果,处理回复结果的库当然是用jQuery。实际上,我们有更好的选择:cheerio。

在node下,使用jQuery,需要使用jsdom库模拟一个window对象,这种方法效率较低,四个字形容就是:笨重稳妥。

如下代码使用jQuery解析haha.html文件

fs=require("fs")
jquery=require('jquery')
jsdom=require('jsdom') //fs.readFileSync()返回结果是一个buffer,相当于byte[] 
html=fs.readFileSync('haha.html').toString('utf8') 
dom=new jsdom.JSDOM(html) 
$=jquery(dom.window) console.log($('h1'))

cheerio只实现了jQuery中的DOM部分,相当于jQuery的一个子集。cheerio的语法和jQuery完全一致,在使用cheerio时,几乎感觉不到它和jQuery的差异。在解析HTML方面,毫无疑问,cheerio是更好的选择。如下代码使用cheerio解析haha.html文件。

cheerio=require('cheerio')
html=require('fs').readFileSync("haha.html").toString('utf8')
$=cheerio.load(html)
console.log($('h1'))

只需20余行,便可实现简单的github爬虫,此爬虫只爬取了一页repo列表。

var axios=require("axios")
var cheerio=require("cheerio")
axios.get("https://github.com/weiyinfu?tab=repositories").then(resp=> {
 var $=cheerio.load(resp.data)
 var lis=$("#user-repositories-list li")
 var repos=[]
 for (var i=0; i < lis.length; i++) {
 var li=lis.eq(i)
 var repo={
 repoName: li.find("h3").text().trim(),
 repoUrl: li.find("h3 a").attr("href").trim(),
 repoDesc: li.find("p").text().trim(),
 language: li.find("[itemprop=programmingLanguage]").text().trim(),
 star: li.find(".muted-link.mr-3").eq(0).text().trim(),
 fork: li.find(".muted-link.mr-3").eq(1).text().trim(),
 forkedFrom: li.find(".f6.text-gray.mb-1 a").text().trim()
 }
 repos.push(repo)
 }
 console.log(repos)
})

三、更丰富的功能

爬虫不是目的,而是达成目的的一种手段。获取数据也不是目的,从数据中提取统计信息并呈现给人才是最终目的。

在github爬虫的基础上,我们可以扩展出更加丰富的功能:使用echarts等图表展示结果。

要想让更多人使用此爬虫工具获取自己的github统计信息,就需要将做成一个网站的形式,通过搜索页面输入用户名,启动爬虫立即爬取github信息,然后使用echarts进行统计展示。网站肯定也要用js作为后端,这样才能和js爬虫无缝衔接,不然还要考虑跨语言调用。js后端有两大web框架express和koa,二者API非常相似,并无优劣之分,但express更加流行。

如上设计有一处用户体验不佳的地方:当启动爬虫爬取github信息时,用户可能需要等待好几秒,这个过程不能让用户干等着。一种解决思路是:让用户看到爬虫爬取的进度或者爬取过程。可以通过websocket向用户推送爬取过程信息并在前端进行展示。展示时,使用类似控制台的界面进行展示。

如何存储爬取到的数据呢?使用MongoDB或者文件都可以,最好实现两种存储方式,让系统的存储方式变得可配置。使用MongoDB时,用到js中的连接池框架generic-pool。

整个项目用到的库包括:

  • express:后端框架
  • cheerio+axios:爬虫
  • ws:websocket展示爬取过程
  • webpack:打包工具
  • less:样式语言
  • echarts:图表展示
  • vue:模板渲染
  • jquery:DOM操作
  • mongodb:存储数据
  • generic-pool:数据库连接池

试用地址:

https://weiyinfu.cn/githubstatistic/search.html?

案例地址:https://github.com/weiyinfu/GithubStatistic

原文链接:https://zhuanlan.zhihu.com/p/53763115