H5开发实践Vue哥要学前端!!

Vue.js起手式+Vue小作品实战

2016-12-14  本文已影响4693人  犯迷糊的小羊

本文是小羊根据Vue.js文档进行解读的第一篇文章,主要内容涵盖Vue.js的基础部分的知识的,文章顺序基本按照官方文档的顺序,每个知识点现附上代码,然后根据代码给予个人的一些理解,最后还放上在线编辑的代码以供练习和测试之用;
在最后,我参考SegmentFault上的一篇技博,对Vue进行初入的实战,目的是将新鲜学到的知识立即派上用场;
如果你还是前端的小白,相信这篇文章可能会对产生一些帮助和引起思想的碰撞,因为大家的学习历程是相似的,遇到的困惑也有一定的共通性,如果文章出现谬误之处,欢迎各位童鞋及时指正;

Vue.js

1. Vue.js是什么

Vue.js(读音 /vjuː/, 类似于 view) 是一套构建用户界面的 渐进式框架。与其他重量级框架不同的是Vue 的核心库只关注视图层。
Vue.js 的目标是通过尽可能简单的 API 实现响应的数据绑定组合的视图组件

Vue.js是一种MVVM框架,其中html是view层,js是model层,通过vue.js(使用v-model这个指令)完成中间的底层逻辑,实现绑定的效果。改变其中的任何一层,另外一层都会改变;

MVVM

2.Vue的基本语法

2.1 Vue构造函数开启Vue之旅

通过构造函数Vue创建一个Vue的根实例

<div id='#el'></div>
---
var vm = new Vue({
  //options
  el:'#el',
  data:{},
  methods:{}
})
---
//扩展Vue构造器
var MyComponent = Vue.extend({
    //扩展选项
})
var vm = new MyComponent({})

解读:


2.2 Vue实例的属性和方法

Vue实例将代理data对象的所有属性,也就是说部署在data对象上的所有属性和方法都将直接成为Vue实例的属性和方法

<div id="app">{{message}}
  <button v-on:click="sayHello">click me</button>
</div>
---
var app = new Vue({
    el:'#app',
    data:{
      message:'hello world!',
      sayHello:function(){
          console.log(1)
      }
  }
})
---
//如果想要获取到app这一实例中选项的对象,Vue提供$进行获取
app.$el === document.getElementById('app')//true
app.$data.message//hello world

【demo】

【TIP】
Vue实例所代理data对象上的属性只有在实例创建的同时进行初始化才具有响应式更新,若在实例创建之后添加是不会触发视图更新的;


2.3数据绑定操作

绑定文本和HTML

<div id = "app">
    {{msg}}
    <div v-html="hi"></div>
</div>
---
var app  = new Vue({
    el: '#app',
    data:{
      msg: 'hello world!',
      hi:'<h1>hi</h1>'
  }
})

解读:

绑定数据在元素的属性

 <div id="app" v-bind:title='message' v-bind:style='red' v-once>
     {{message}}
  </div>
---
var app = new Vue({
  el: '#app',
  data:{
    message: 'hello world!',
    red: 'color:red'
  }
})

解读:

使用JS表达式处理数据

 <div id='#app'>
    <p v-once>{{num + 10 }}</p>
    <p v-if='seen'>{{message + 'jirengu'}}</p>
</div>
---
var app = new Vue({
  el: '#app',
  data:{
    num:10,
    message: 'hello world!',
    seen:true
  }
})

【demo】

使用过滤器来格式化数据

<div id="app" >
    <p v-if='seen'>{{message | capitalize}}</p>
  </div>
---
var app = new Vue({
  el: '#app',
  data:{
    message: 'hello world!',
    seen:true,
  },
  filters:{
    capitalize:function(value){
      if(!value) return ''
      value = value.toString()
      return value.charAt(0).toUpperCase() + value.slice(1)
    }
  }
})

【demo】

条件指令控制DOM元素的显示操作

<div id="app" >
     <p v-if='seen'>{{message}}</p>
  </div>
---
var app = new Vue({
  el: '#app',
  data:{
    message: 'hello world!',
    seen:true
  }
})

解读:

循环指令实现数据的遍历

 <div id="app">
    <ol>
      <li v-for='item in items'>
        {{ item.text }}
      </li>
    </ol>
</div>
---
var app = new Vue({
  el: '#app',
  data:{
    items:[
      {text:'Vue'},
      {text:'React'},
      {text:'Angular'}
    ]
  }
})

解读:

【demo】

事件绑定指令可以实现事件监听

<div id='app'>
  <p>{{message}}</p>
  <button v-on:click='reverseMessage'>reverseMesssage</button>
</div>
---
var app = new Vue({
  el: '#app',
  data:{
    message: 'hello world!'
  },
  methods:{
  reverseMessage:function(){
    this.message = this.message.split('').reverse().join('')
    }
  }
})

解读:

【demo】

小结

本章涉及Vue的基础的数据绑定操作,内容包括:


2.4计算属性

使用计算属性完成一些数据计算操作

 <div id="app" >
    <p>Original message : {{message}}</p>
    <p>Reversed message : {{ReversedMessage}}</p>
  </div>
---
var app = new Vue({
  el: '#app',
  data:{
    message: 'hello world!',
  },
  computed:{
    ReversedMessage:function(){
     return  this.message.split('').reverse().join('')
    }
  }
})

解读:

计算属性 VS Methods

  <div id="app" >
    <p>Original message : {{message}}</p>
    <p>Reversed message : {{ReversedMessage}}</p>
     <p>Reversed message:{{reversedMessage()}}</p>   
  </div>
---
var app = new Vue({
  el: '#app',
  data:{
    message: 'hello world!',
  },
  computed:{
    ReversedMessage:function(){
     return  this.message.split('').reverse().join('')
    }
  },
  methods:{
    reversedMessage:function(){
     return  this.message.split('').reverse().join('')
    }
  }
})

解读:

计算属性的setter

Vue实例的computed对象默认只有getter,如果你要设置数据,可以提供一个setter,即设置器;

<div id="app" > 
    <p>Hi,I'm{{fullName}}</p>
</div>
---
var app = new Vue({
  el: '#app',
  data:{
    message: 'hello world!',
    name:'Teren'
  },
  computed:{
    fullName:{
      get:function(){
         return this.name   
      },
      set:function(value){
        this.name = value
      }
    }
  }
})

2.5Class与Style的绑定

绑定Class

<div id="app" >
    <!-- 直接绑定对象的内容 -->
      <p class='static' v-bind:class="{active:isActive,error:hasError}">Hello world!</p>
   <!--  绑定对象 -->
 <p v-bind:class="classObj">こんにちは </p>    
   <p v-bind:class='style' >你好</p>
    <!-- 绑定数组 -->
    <p v-bind:class="[staticClass,activeClass,errorClass]">
Olá</p>
    <button @click='changeColor'>click me</button>
  </div>
---
//css
.static{
  width: 200px;
  height: 100px;
  background: #ccc;
}
.active{
  color:red;
}
.error{
  font-weight: 800;
}
---
var app = new Vue({
  el: '#app',
  data:{
   isActive:true,
   hasError:true,
   classObj:{
     static:true,
     active:true,
     error:true,
   },
  staticClass:'static',
  activeClass:'active',
  errorClass:'error',
  
  },
  computed:{
    style:function(){
      return {
        active: this.isActive,
        static:true,
        error:this.hasError
      }
    }
  },
  methods:{
    changeColor:function(){
      this.isActive = !this.isActive
    }
  }
})

解读:

data:{
   classObj:{
     static:true,
     active:true,
     error:true,
   }
data:{
  staticClass:'static',
  activeClass:'active',
  errorClass:'error',
  }

【TIP】无论是哪种方式,前提都是css中的class要先设定

【demo】

绑定style

  <div id="app" >
    <p v-bind:style='styleObj'>Hello World!</p>
    <p v-bind:style='[styleObj,bgObj]'>你好</p>
  </div>
---
var app = new Vue({
  el: '#app',
  data:{
    styleObj:{
    fontWeight:800,
    color:'red'
  },
    bgObj:{
      width:'100px',
      height:'80px',
      background:'#ccc'
    }
  },
})

解读:

【demo】

2.6条件渲染和列表渲染

前面简单介绍了一下v-ifv-forv-on指令,下面的部分将详细介绍以上3个指令;

条件渲染

<div id="app" >
  <p v-if='ok'>Hello World!</p>
  <p v-else>Hello Universal</p>
  <template v-if='motto'>
     <h1>Steve Jobs</h1>
     <p>motto:stay hungry ! stay foolish</p>
  </template>
  <p v-show='ok'>Show Me</p>
  </div>
---
var app = new Vue({
  el: '#app',
  data:{
     ok:true,
     motto:true,
  },
})

解读:

【TIP】 v-if和v-show的区别

【demo】

列表渲染

<div id="app" >
    <ol>
      <li v-for='car in cars'>
         {{car.name}}
      </li>
    </ol>
    <ul>
      <li v-for='(food,index) in foods'>
      {{index}}---{{food}}---{{delicious}}
      </li>
    </ul>
    <ul>
      <li v-for='(value,key,index) in object'>
        {{index}}.{{key}}.{{value}}
      </li>
    </ul>
    <div>
      <span v-for='n in 10' style="margin-left:5px">{{n}}</span>
    </div>
       <span v-for='n in evenNumbers' style="margin-left:5px">{{n}}</span>
    </div> 
   <!--  <div>
       <span v-for='n in odd(counts)' style="margin-left:5px">{{n}}</span> 
    </div> -->
  </div>
---
var app = new Vue({
  el: '#app',
  data:{
    delicious:'delicious',
     cars:[
       {name:'Benz'},
       {name:'BMW'}
     ],
    foods:[
      'tomato',
      'potato',
      'ice cream'
    ],
    object :{
      name:'Benz',
      age:'18'
    },
    numbers:[1,2,3,4,5,6,7,8,9,10],
    counts:[1,2,3,4,5]
  },
  computed:{
      evenNumbers:function(){
        return this.numbers.filter(function(number){
          return number%2 === 0
        })
      }
  },
  methods:{
    odd:function(counts){
     return counts.filter(function(count){
        return count%2 === 1;
      })
    }
  }
})

解读:

data:{
//数字数组
  numbers:[1,2,3,4,5,6,7,8,9,10],
  counts:[1,2,3,4,5]
//字符串数组
  foods:[
      'tomato',
      'potato',
      'ice cream'
    ],
//对象数组
    cars:[
       {name:'Benz'},
       {name:'BMW'}
     ],
//对象
 object :{
      name:'Benz',
      age:'18'
    },
}
//数据为数字数组
<div>
  <span v-for="n in numbers">{{n}}</span>
</div>
---
//数据为字符数组
<ul>
    <ol v-for='food in foods'>{{food}}</ol>
</ul>
---
//数据为对象
<ul>
  <ol v-for="value in object">{{value}}</ol>
</ul>
//或者
<ul>
  <ol v-for="(value,key,index) in object">{{index}}.{{key}}.{{value}}</ol>
</ul>
---
//数据为对象数组
<ul>
  <ol v-for="car in cars">{{car.name}}</ol>
</ul>

【demo】


2.7 事件监听

简单的事件监听——直接在指令上处理数据

<div id="#app">
    <p v-on:click="counter+=1">{{counter}}</p>
</div>
---
var app = new Vue({
  el: "#app",
  data:{
    counter: 0,
  }
})

复杂的事件监听——在methods对象定义回调函数

<div id="#app">
    <p v-on:click="greet">{{vue}</p>
</div>
---
var app = new Vue({
  el: "#app",
  data:{
       vue:"hello Vue.js"
  },
methods:{
    greet:function(event){
          console.log(this.vue)
      }
  }
})

事件修饰符——调用事件对象函数的快捷方式

  <div v-on:click.prevent="greet">1</div>//等价于event.preventDefault()
  <div v-on:click.stop="greet">2</div>//等价于event.stopPropagation()
  <div v-on:click.capture="greet">3</div>//等价于事件回调函数采用捕获阶段监听事件
  <div v-on:click.self="greet">4</div>//等价于event.target

按键修饰符——按键事件的快捷方式

常见按键别名包括:
- enter
- tab
- delete
- esc
- space
- up
- down
- left
- right

【demo】


2.8 表单控件绑定

文本控件

<div id="app">
    <p>{{message}}</p>
    <input type="text" v-model='message'>
  </div>
---
var app = new Vue({
  el:'#app',
  data:{
    message:'Hello World!'
  },
})

解读:

单选控件

 <input id="man" value="man" type="radio" v-model='picked'>
    <label for="man">Man</label>
    <br>
     <input id="woman" value="woman" type="radio" v-model='picked'>
    <label for="woman">Woman</label>
    <div style="margin-left:10px">{{picked}}</div>
---
var app = new Vue({
  el:'#app',
  data:{
    message:'Hello World!',
    picked:'man'
  },
})

解读:

复选框

 <input type="checkbox" id="Benz" v-model='checked' value='Benz'>
    <label for="Benz">Benz</label>
   <input type="checkbox" id="BMW" v-model='checked' value="BMW">
    <label for="BMW">BMW</label>
    <div>Checked Name:{{checked}}</div>
---
var app = new Vue({
  el:'#app',
  data:{
    message:'Hello World!',
    picked:'man',
    selected:"A",
    checked:[],
  },
})

【demo】


2.9 组件

组件可以扩展 HTML 元素,封装可重用的代码。在较高层面上,组件是自定义元素;
通过Vue.component()接口将大型应用拆分为各个组件,从而使代码更好具有维护性、复用性以及可读性

注册组件

<div id="app">
   <my-component></my-component>
  </div>
---

Vue.component('my-component',{
  template:'<div>my-first-component</div>'
})

var app = new Vue({
  el:'#app',
  data:{
  }
})

解读:

局部注册组件

  <div id="app">
   <my-component>
     <heading></heading>
   </my-component>
  </div>
---
Vue.component('my-component',{
  template:'<div>my-first-component</div>'
})

var Child = {
  template: '<h3>Hello World</h3>'
}

var app = new Vue({
  el:'#app',
  components:{
    'my-component':Child
  }
})

解读:

特殊DOM模板将会限制组件的渲染

像这些包含固定样式的元素<ul>, <ol>, <table>, <select>
自定义组件中使用这些受限制的元素时会导致渲染失败;
通的方案是使用特殊的 is属性:

 <table>
      <tr is="my-component">
 </table>

创建组件的data对象必须是函数

<counter></counter>
 <counter></counter>
 <counter></counter>
---
Vue.component('counter',{
  template:'<button @click="count+=1">{{count}}</button>',
  data:function(){
    return {
      count: 0
    }
  }
})

解读:

使用Props实现父组件向子组件传递数据

<child some-text='hello'></child>
    <br>
    <child v-bind:some-text='message'> </child>
---
Vue.component('child',{
  template:'<div>{{someText}}</div>',
  props:['someText']
})
var app = new Vue({
  el:'#app',
  components:{
    'my-component':Child
  },
  data:{
    message:"你好"
  }
})

解读:

【demo】

父组件是使用 props 传递数据给子组件,但如果子组件要把数据传递回去则使用自定义事件!

 <div id="app">
      <p>{{total}}</p>
      <button-counter v-on:increment='incrementTotal'></button-counter>
      <button-counter @increment='incrementTotal'></button-counter>
  </div>
---
Vue.component('button-counter',{
  template:'<button v-on:click="increment">{{counter}}</button>',
  data:function(){
    return {
      counter:0
    }
  },
  methods:{
    increment:function(){
      this.counter +=1;
      this.$emit('increment')
    }
  }
})

var app = new Vue({
  el:'#app',
  data:{
    total:0
  },
  methods:{
    incrementTotal:function(){
      this.total += 1;
    }
  }
})

解读:

使用Slots分发内容

内容分发指的是混合父组件的内容与子组件自己的模板;

<div id="app">
     <h1>I'm the parent title</h1>
  <my-component>
    <p>This is some original content</p>
    <p>This is some more original content</p>
  </my-component>
    <hr>
  </div>
---
Vue.component('my-component',{
  template:"<div><h2>I'm the child title</h2><slot>如果没有分发内容则显示我。</slot></div>"
})
var app = new Vue({
  el:'#app',
  data:{
  }.
})

解读:

//子组件app-layout模板
<div class="container">
<header>
<slot name="header"></slot>
</header>
<main>
<slot></slot>
</main>
<footer>
<slot name="footer"></slot>
</footer>
</div>
//父组件模板
<app-layout>
<h1 slot="header">Here might be a page title</h1>

<p>A paragraph for the main content.</p>
<p>And another one.</p>

<p slot="footer">Here's some contact info</p>
</app-layout>
//渲染结果
<div class="container">
<header>
<h1>Here might be a page title</h1>
</header>
<main>
<p>A paragraph for the main content.</p>
<p>And another one.</p>
</main>
<footer>
<p>Here's some contact info</p>
</footer>
</div>

解读:

【TIP】关于组件的命名规范

// 在组件定义中
components: {
// 使用 camelCase 形式注册
'kebab-cased-component': { /* ... */ },
'camelCasedComponent': { /* ... */ },
'TitleCasedComponent': { /* ... */ }
}
<kebab-cased-component></kebab-cased-component>
<camel-cased-component></camel-cased-component>
<title-cased-component></title-cased-component>

【demo】


2.10 vue-resource插件

使用vue-rescource实现前后端的通信

在vue实例中新增ready对象,当页面完成加载时发出请求

 new Vue({
    el: '#app',
    ready: function() {
        this.$http.get('book.json', function(data) {
            this.$set('books', data);
        }).error(function(data, status, request) {
            console.log('fail' + status + "," + request);
        })
      //post方法:this.$http.post(url,postdata,function callback)
    },
    data: {
        ....
        books:''
    },
    .....

【TIP】

这个$http请求和jquery的ajax还是有点区别,这里的post的data默认不是以form data的形式,而是request payload。解决起来也很简单:在vue实例中添加headers字段:

http: { headers: {'Content-Type': 'application/x-www-form-urlencoded'} }

3. 实战之Vue小作品

Hello Vue.js

【Hello Vue.js】

上面的Vue小作品是小羊仿照SegmentFault的一篇技博的练手之作,建议各位对照源码亲手练习一次,以便初步熟悉Vue的使用;

【注】版权归犯迷糊的小羊所有,转载请联系作者。


参考资料:

上一篇下一篇

猜你喜欢

热点阅读