媒介
本文纯属个人日常平凡实践过程当中的一些经验总结,算是一点点小技能吧,不是何等高妙的手艺,假如对你有协助,那末不胜幸运。
本文不触及稀有API
运用要领等,大部份内容都是基于对vue的一些实践罢了。由于涉嫌投机倒把,能够会带来一些不符合范例的副作用,请依据项目要求酌情运用。
多个页面都运用的到要领,放在
vue.prototype
上会很轻易刚打仗
vue
的时刻做过一件傻事,由于封装了一个异步要求接口post
,放在post.js
文件内里,然后在每一个须要运用异步要求的页面引入import port from './xxxx/xxxx/post'
假如只是如许,还没什么,我们能够写好一个页面今后再复制,能够保证每一个页面都有上面的语句。然则假如每一个文件地点的目次层级不一样呢?
// 假定一般是如许 import port from '../xxxx/xxxx/post' // 目次加深一级,就变成如许 import port from '../../xxxx/xxxx/post' // 再加深一级的模样 import port from '../../../xxxx/xxxx/post'
固然,这个时刻,我们能够用 别号
@/xxxx/post
,然则照样少不了要每一个页面援用。
那我们来看看,用vue.prototype
有多轻易?
起首,你得在vue
的进口文件(vue-cli
天生的项目标话,默许是/src/main.js
)内里做以下设置import port from './xxxx/xxxx/post' vue.prototype.$post = post
如许,我们就可以够在一切的
vue
组件(页面)内里运用this.post()
要领了,就像vue
的亲儿子一样tip: 把要领挂在到
prototype
上的时刻,最好加一个
$
前缀,防止跟其他变量争执til again: 不要挂载太多要领到
prototype
上,只挂载一些运用频次异常高的须要响应的数据,在猎取到接口数据的时刻,先设置
人人有无很常常遇到如许都一种状况,在轮回列表的时刻,我们须要给列表项一个掌握显现的属性,如 是不是可删除,是不是已选中等等,然后端接口平常不会返回这类字段,由于这属于纯前端展现的,跟后端没啥关联,比方后端给的数据以下
[ {name: 'abc', age: 18}, {name: 'def', age: 20}, {name: 'ghi', age: 22}, ]
我们无妨假定以上数据为门生列表
然后我们须要衬着这个列表,在每一项背面显现一个勾选按钮,假如用户打勾,则这个按钮是绿色,默许这个按钮是灰色,这个时刻,上表是没有满足这个衬着前提的数据,而假如我们在用户打勾的时刻,再去增加这个数据的话,一般的做法是没法及时响应的。
假如我们在猎取到数据的时刻,先给数组的每一项都加一个是不是打勾的标示,就可以够处置惩罚这个题目,我们假定我们猎取到的数据是
res.list
res.list.map(item => { item.isTicked = false })
这么做的原理是
vue
没法对不存在的属性作响应,所以我们在猎取到数据的时刻,先把须要的属性加上去,然后在赋值给data
, 如许data
接收到数据的时刻,已经是存在这个属性了,所以会响应。固然另有其他要领能够完成。不过关于一个强迫症来讲,我照样比较倾向于这类做法封装全局基于
promise
的异步要求要领看过许多项目标源码,发明大部份的异步要求都是直接运用
axios
之类的要领,以下axios({ method: 'post', url: '/user/12345', data: { firstName: 'Fred', lastName: 'Flintstone' } }) .then(function (response) { console.log(response); }) .catch(function (error) { console.log(error); });
假如有跨域,或许须要设置
http
优等,还须要到场更多的设置,而这些设置,关于同一个项目来讲,基础都是一样的,不一样的只需url
跟参数,既然如许,那我吗为何不把它封装成一个要领呢?function post (url,param) { return axios({ method: 'post', url: url, data: param ... axios 的其他设置 }) }
tip: 这里本来我多用了一层promise包起来,对简朴的需求来讲是太过剩了,以为掘金用户
@日月为易。
指出再连系第一点,我们就可以够再恣意
vue
实例中如许运用let param = { firstName: 'Fred', lastName: 'Flintstone' } this.post('/user/12345',param) .then(...) .catch(...)
有无比原始的简朴许多呢?假如你的项目支撑
async
await
,还能够如许用let param = { firstName: 'Fred', lastName: 'Flintstone' } let res = await this.post('/user/12345',param) console.log(res) // res 就是异步返回的数据
tip:
await
关键字必须在
被 async 润饰的函数内里运用
假如你以为有时刻,你真的须要父子组件同享一个值,不如尝尝传个援用范例过去
vue
的父子组件传值,有很多种要领,这里就不一一列举了,然则本日我们要相识的,是应用javascript
的援用范例特征,还到达另一种传值的目标假定有这么一个需求,父组件须要传 3 个值到子组件,然后再子组件内里修改后,须要立马再父组件上作出响应,我们一般的做法上改完今后,经由过程
this.$emit
发射事宜,然后再父组件监听对应的事宜,但是这么做应对一两个数据还好,假如传的数据多了,会累死人。
我们无妨把这些要通报的数据,包再一个对象/数组 内里,然后在传给子组件<subComponent :subData="subData"></subComponent>
data () { return { subData: { filed1: 'field1', filed2: 'field2', filed3: 'field3', filed4: 'field4', filed5: 'field5', } } }
如许,我们在子组件内里修改
subData
的内容,父组件上就可以直接作出响应,无需this.$emit
或vuex
而且假如有其他兄弟组件的话,只需兄弟组件也有绑定这个subData
,那末兄弟组件内里的subData
也能及时响应tip: 起首,这么做我个人上以为有点不符合范例的,假如没有迥殊多的数据,照样乖乖用
this.$emit
吧,其次,这个数据须要有特定的前提才组织的出来,并非一切状况都实用。异步要求的参数在
data
内里组织好,用一个对象包起来,会轻易许多有做过相似
ERP
范例的体系的同砚,一定遇到过如许的一个场景,一个列表,有 N 个过滤前提,这个时刻一般我们这么绑定<input type="text" v-model="field1"> <input type="text" v-model="field2"> <input type="text" v-model="field3"> .... <input type="text" v-model="fieldn">
data () { return { field1: 'value1', field2: 'value2', field3: 'value3', ... fieldn:'valuen' } }
然后提交数据的时刻如许:
var param = { backend_field1: this.field1, backend_field2: this.field2, backend_field3: this.field3, ... backend_fieldn: this.fieldn } this.post(url,param)
如你看到的,每次提交接口,都要去组织参数,还很轻易脱漏,我们无妨如许:先去接口文档内里看一下后端须要的字段称号,然后
<input type="text" v-model="queryParam.backend_field1"> <input type="text" v-model="queryParam.backend_field2"> <input type="text" v-model="queryParam.backend_field3"> .... <input type="text" v-model="queryParam.backend_fieldn">
```javascript data () { return { queryParam:{ backend_field1: 'value1' backend_field2: 'value2' backend_field3: 'value3' ... backend_fieldn: 'valuen' } } } ``` 然后提交数据的时刻如许: ```javascript this.post(url,this.queryParam) ```
是的,如许做也是有局限性的,比方你一个数据在 2 个处所共用,比方前端组件绑定的是一个数组,你须要提交给后端的是 2 个字符串(例:
element ui
的时候控件),不过部份特别题目轻微处置惩罚一下,也比从新构建一个参数简朴不是吗?data
内里的数据多的时刻,给每一个数据加一个备注,会让你后期往回看的时刻很清楚续上一点,
data
内里有许多数据的时刻,能够你写的时刻是挺清楚的,毕竟都是你自身写的东西,但是过了十天半个月,或许他人看你的代码,置信我,不管是你自身,照样他人,都是一头雾水(记忆力超越凡人的除外),所以我们无妨给每一个数据背面加一个备注data () { return { field1: 'value1', // 掌握xxx显现 field2: 'value2', // 页面加载状况 field3: [], // 用户列表 ... fieldn: 'valuen' // XXXXXXXX } }
逻辑庞杂的内容,只管拆成组件
假定我们有一个如许的场景:
<div> <div>姓名:{{user1.name}}</div> <div>性别:{{user1.sex}}</div> <div>岁数:{{user1.age}}</div> ...此处省略999个字段... <div>他隔壁邻居的阿姨家小狗的名字:{{user1.petName}}</div> </div> <-- 固然,显现中我们不会傻到不必 v-for,我们假定这类状况没法用v-for --> <div> <div>姓名:{{user2.name}}</div> <div>性别:{{user2.sex}}</div> <div>岁数:{{user2.age}}</div> ...此处省略999个字段... <div>他隔壁邻居的阿姨家小狗的名字:{{user2.petName}}</div> </div>
这类状况,我们无妨把[用户]的代码,提取到一个组件内里:
假定以下代码,在comUserInfo.vue
<template> <div> <div>姓名:{{user.name}}</div> <div>性别:{{user.sex}}</div> <div>岁数:{{user.age}}</div> ...此处省略999个字段... <div>他隔壁邻居的阿姨家小狗的名字:{{user.petName}}</div> </div> </template> <script > export default { props:{ user:{ type:Object, default: () => {} } } } </script>
然后本来的页面能够改成如许(省略掉导入和注册组件,假定注册的名字是
comUserInfo
):<comUserInfo :user="user1"/> <comUserInfo :user="user2"/>
如许是不是是清楚许多?不必看解释,都能猜的出来,这是2个用户信息模块, 如许做,另有一个优点就是涌现毛病的时刻,你能够更轻易的定位到毛病的位置。
假如你只在子组件内里转变父组件的一个值,无妨尝尝
$emit('input')
,会直接转变v-model
我们一般的父子组件通讯是 父组件经由过程
props
传给子组件,子组件经由过程this.$emit('eventName',value)
关照父组件绑定在@eventName
上的要领来做响应的处置惩罚。
然则这边有个惯例,vue
默许会监听组件的input
事宜,而且会把子组件内里传出来的值,赋给当前绑定到v-model
上的值一般用法 – 父组件
<template> <subComponent :data="param" @dataChange="dataChangeHandler"></subComponent> </template> <script > export default { data () { return { param:'xxxxxx' } }, methods:{ dataChangeHandler (newParam) { this.param = newParam } } } </script>
一般用法 – 子组件
<script > export default { methods:{ updateData (newParam) { this.$emit('dataChange',newParam) } } } </script>
应用默许
input
事宜 – 父组件<template> <subComponent v-model="param"></subComponent> </template>
应用默许
input
事宜 – 子组件<script > export default { methods:{ updateData (newParam) { this.$emit('input',newParam) } } } </script>
如许,我们就可以免却父组件上的一列席处置惩罚代码,
vue
会自动帮你处置惩罚好tip: 这类要领只实用于转变单个值的状况,且子组件对父组件只需简朴的传值,不须要其他附加操纵(如更新列表)的状况。
补充一个
this.$emit('update:fidldName',value)
要领 (谢谢掘金用户@日月为易。
指出)
详细用法以下:父组件
<subComponent field1.sync="param1" field2.sync="param2"></subComponent>
子组件
<script > export default { methods:{ updateData1 (newValue) { this.$emit('update:field1',newValue) }, updateData2 (newValue) { this.$emit('update:field2',newValue) } } } </script>
该要领,个人认为比较实用于 要更新的数据不能绑定在
v-model
的状况下,或许要双向通讯的数据大于 1 个(1个也能够用,但我个人更引荐input
的体式格局, 看个人喜好吧),但又不会许多的状况下.conponents
放在Vue options
的最上面不知道人人有无如许的阅历: 导入组件,然后在也页面中运用,好的,报错了,为啥?遗忘注册组件了,为何会常常遗忘注册组件呢?由于一般的一个
vue
实例的构造大概是如许的:import xxx form 'xxx/xxx' export default { name: 'component-name', data () { return { // ...依据营业逻辑的庞杂水平,这里省略多少行 } }, computed: { // ...依据营业逻辑的庞杂水平,这里省略多少行 }, created () { // ...依据营业逻辑的庞杂水平,这里省略多少行 }, mounted () { // ...依据营业逻辑的庞杂水平,这里省略多少行 }, methods () { // ...依据营业逻辑的庞杂水平,这里省略多少行 }, }
我不知道人人一般是把
components
属性放在哪一个位置,横竖我之前是放在最底下,效果就是致使常常犯上述毛病。背面我把
components
调到第一个去了import xxx form 'xxx/xxx' export default { components: { xxx }, // 省略其他代码 }
从此今后,妈妈再也不必忧郁我遗忘注册组件了,导入和注册都在同一个位置,想遗忘都难。
大部份状况下,生命周期内里,不要有太多行代码,能够封装成要领,再挪用
看过许多代码,包含我自身之前的,在生命周期内里洋洋洒洒的写了一两百行的代码,如:把页面加载的时刻,该做的事,悉数写在
created
内里,致使全部代码难以浏览,完整不知道你在页面加载的时刻,做了些什么,
这个时刻,我们无妨把那些逻辑封装成要领,然后在生命周期内里直接挪用:created () { // 猎取用户信息 this.getUserInfo() // 猎取体系信息 this.getSystemInfo() // 猎取设置 this.getConfigInfo() }, methods:{ // 猎取用户信息 getUserInfo () {...}, // 猎取体系信息 getSystemInfo () {...}, // 猎取设置 getConfigInfo () {...}, }
如许是不是是一眼就可以看的出,你在页面加载的时刻做了些什么?
tip: 这个应当算是一个约定俗成的范例吧,只是以为看的比较多如许写的,加上我自身初学的时刻,也这么做了,所以写出来,愿望新入坑的同砚能防止这个题目
- 罕用
watch
,假如你以为你很多处所都须要用到watch
,那十有八九是你对vue
的API
还不够相识vue
自身就是一个数据驱动的框架,数据的更改,能及时反应到视图上去,假如你想要依据数据来掌握试图,一般状况一下合营computed
服用就可以处置惩罚大部份题目了,而视图上的更改,我们平常能够经由过程监听input
change
等事宜,到达及时监听的目标,
所以很少有需求运用到watch
的时刻,最少我近来到的十来个项目内里,是没有用过watch
固然,并非说watch
是一定没用途,vue
供应这个api,一定是有他的原理,也有部份需求是真的须要用到的,只是我以为应当很罕用到才对,假如你以为随处都得用到的话,
那末我以为 十有八九你应当多去熟习一下computed
和vue
的其他api
了
末了
本文的github地点 迎接随便star,follow, 和 不随便的 issue
别的,github上另有其他一些关于前端的教程和组件,
有兴致的童鞋能够看看,你们的支撑就是我最大的动力。