[关闭]
@lizlalala 2017-01-04T10:29:02.000000Z 字数 4932 阅读 1493

vue组件学习

vue 组件


最近一直困惑于mv*模式,因此想分别试一下vue的mvvm,以及backbone的mvc,重构一下之前用jquery写的最原始版本的todo。 那么第一部分便是vue的学习啦。

vue

之前的博客里面,我们讲了vue的数据绑定以及它的用法,这一篇主要尝试它的组件化部分,与react的组件化的异同之处,以及在开发过程中尝试理解它的mvvm的思想。
ps:之前的数据绑定,因为当时公司的版本是旧的,为了继续在前fe的基础上继续写,不得已用的是0.12的版本,今天这篇的版本是1.0:)

组件化

props:

查看vue component教程,总结来说,它是react props的扩展版本。
(1)相同的地方在于:props也是默认单向数据流,从父组件传递属性到子组件。
(2)之所以说扩展,体现在两个方面:

让我们看第一个扩展。

vue的props提供了两种使用方法,静态的+动态绑定。
用react的方式来理解的话:

vue组件化demo@luchenCodePen

  1. //html
  2. <div class="childWrapper">
  3. <input v-model="dynamicMsg">
  4. <br><span>静态绑定:</span>
  5. <child parent-msg="dynamicMsg"></child>
  6. <br><span>动态绑定到父元素:</span>
  7. <child :parent-msg="dynamicMsg"></child>
  8. </div>
  1. //javascript
  2. Vue.component('child', {
  3. props: ['parentMsg'],
  4. template: '<span>{{ parentMsg }}</span>'
  5. })
  6. var parent = new Vue({
  7. el:".childWrapper",
  8. data:{
  9. dynamicMsg:"hello"
  10. }
  11. })

注意点:
1. js中的camel写法对应于html中的kebab-case
2. 如果 prop 是一个对象或数组,是按引用传递。在子组件内修改它会影响父组件的状态,不管是使用哪种绑定类型。就变成了双向绑定了
3. 如果props是数组,则需要按照动态绑定来写,使得看成变量、表达式,否则会以字符串传递。
===更新2017/1/4
4. 父组件传进来的props作为子组件data的初始值存在的话,如果它变动,内部data是不能响应的,需要设置watch(props),保持data始终在props的基础上变动

再看看第二个扩展
react的props是单向数据流,而vue中还可以实现双向的绑定。
但是最好还是不要这么做,因为父组件有很多子组件,每个都进行双向绑定的话,会有各种冲突问题,而且光看父组件的信息,很难理解父组件的状态

  1. <child :msg.sync="parentMsg"></child>

通常是用v-bind来绑定数据,实现js中传值使得数据渲染,在交互频繁的表单上,可以用v-model进行双向绑定。

计算属性

也有双向绑定的含义,watch+反向set

双向props示例

  1. //child
  2. <modal :category="category" title="禁发" :order="order" :show.sync="showModal"></modal>

parent会对showModal这个变量进行变动。

  1. //parent button点击响应事件
  2. showDetail(){
  3. console.log(" ==== ", this.showModal);
  4. this.showModal = true;
  5. },

在modal内部

  1. <div class="modal" v-show="show"> //here
  2. <div class="modal-dialog">
  3. <div class="modal-content">
  4. <div class="modal-header">
  5. <button type="button" class="close" data-dismiss="modal" aria-hidden="true" @click="closeModal">&times;</button>
  6. <h4 class="modal-title">{{category}}</h4>
  7. </div>
  1. export default {
  2. name:"PopModal",
  3. props:["category","order","show"], //表明从父元素传递下来
  4. data () {
  5. return{
  6. }
  7. }
  8. method(){
  9. closeModal(){
  10. this.show = false;
  11. },
  12. }

需要注意的是,如果modal绑定的时候是单向的,即 :show = "showModal",那么子组件内部使得show = false的时候,父组件的showModal还是保持true的状态。那么会导致父的状态是显示,子状态是不显示,那么点击 showPop按钮的时候是无法显示的。应该改为双向上。

  1. //update
  2. <modal :category="category" title="禁发" :order="order" :show.sync="showModal"></modal>

开发杂项

  1. scope 限制css
    A组件,B组件都引入到组件C中,但是A,B都有同样的样式.class name,那么会冲突,因此需要用scope 去进行限制,而且需要注意的是在style里面进行 import,scope是不起作用的。只能inline css
  1. <style lang="scss" scoped>
  2. .modal{
  3. display: block;
  4. display: flex;
  5. align-items:center;
  6. justify-content:center;
  7. background-color: rgba(11, 11, 11, 0.6);
  8. .action{
  9. cursor: pointer;
  10. }
  11. }
  12. .modal-dialog{
  13. max-width: 30%;
  14. }
  15. </style>
  1. vue-router 注意事项
  1. <ul class="nav nav-tabs">
  2. <li class=""><a v-link=" '/event/list' " >信息列表</a></li>
  3. <li><a v-link=" '/event/create' " >创建事件</a></li>
  4. </ul>

这边的v-link 跟v-on一样,里面的默认是一个变量,如果想传递字符串进去,需要另加单引号

同理,@click,看这个例子

  1. // toggleActive()里面的如果直接是A,会认为是一个变量,无法得到,需要变成字符串
  2. <li :class="['tab-item',isA?'tab-active':''] " @click="toggleAcitive('A')"><a v-link=" '/event/list' " >信息列表</a></li>
  3. <li :class="['tab-item',!isA?'tab-active':''] " @click="toggleAcitive('B')"><a v-link=" '/event/create' ">创建事件</a></li>

3, class 动态绑定

  1. <li class="pageList[0]===1?'disabled':''">

这样是无法识别的,里面不是三元符,而是就是 一个字符串,需要加bind绑定才会变成三元表达式

  1. :class="[ 'tag', {active: item.id===filterCategory.id}]"

4,input checkbox绑定到一个数组的时候,需要指定他们的value,否则相当于一个,会同时选中或不选中,指定后才会各自控制。

  1. ajax ui体验优化
  1. handleEventEdited(data){
  2. //直接更新
  3. var temp = Object.assign({},this.eventList);
  4. this.eventList = this.eventList.map(event=>{
  5. if(event.name==data.name)
  6. return Object.assign({},event,{name:data.newName});
  7. else return event;
  8. });
  9. //发送请求
  10. this.$http.post(server_path+"/event",data).then((response)=>{
  11. console.log("事件修改成功");
  12. },(err)=>{
  13. //修改失败后回退
  14. this.eventList = temp;
  15. console.log("事件修改失败");
  16. });
  17. },
  1. 生命周期

楼主最近的开发过程中遇到这么一个问题,单页应用,最外层组件为app.vue。内层靠路由嵌套了几个子组件。子组件页面一加载就需要去发请求获取数据,而请求的param里面依赖父组件获得的数据。

在no组件,no单页的情况下,这种可以用一个页面加载同步请求去搞定。但是现在不允许这样。还牵扯到该在哪个合适的生命周期里去发送请求的问题。

困惑点1:
之前写react的时候,官方建议在componentDidMount里面进行fetch,但是我比较疑惑的是为什么不在componentWillMount或者render里面操作。因为1,数据取得后就一直存在着,mount以后肯定可以显示。2,难道是因为willMount和render是在dom渲染,可能阻塞ui线程的问题。但是ajax是另开一个线程啊,应该是不影响的啊。

科普一下vue的生命周期,楼主大概打印了一下mount之前的执行顺序。

父子组件生命周期

结合官网的生命周期列表,我们可以看到,都会经历如下的过程:

beforeCreated-> 生成data,computed 这些数据,初始化事件
->created,实例对象被创建
-> 在从created到beforeMount过程中编译模板(template)
-> 编译完成后将template插入el或者父html中,这就完成了mounted。

而对于父组件,因为嵌套了子组件,它的mount需要等到子组件都处理完,生成el并插入document后才算完成。也就解释了上面打印的内容。

现在的规划大概是这样的,在父组件created的时候去fetch数据。然后在子组件中用v-if='isParentDataGot' 来确定装载与否。因为上面我们说了,子组件先创建实例,去计算这些data,既然父组件数据还未获取。那么本组件v-if === false。不显示
但是子组件的生命周期还在进行。只是当父组件获取到后update,把数据附上去,
然后在mounted里面去发送自己的请求。

困惑点2:
楼主想知道是否可以在beforeMount里面return false来控制是否装载。
困惑点3:
一般是在mounted发送请求,那么vue现在的生命周期中,在created,beforeMount这些里面发送会有什么影响。

知识回顾

  1. mouseenter mouseover区别
    mouseenter只在刚进入某个元素时触发,不会冒泡
    而mouseover在进入,以及在该元素上移动时都会触发

  2. git远程合并
    楼主是项目owner的话,接受远程pull request后merge到dev分支。
    本地

  1. git fetch bit-origin dev:new-branch
  2. git checkout new-branch 查看最新代码。如果可以的话
  3. git checkout dev
  4. git merge new-branch。使得dev为最终代码
  5. git remove new-branch
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注