3
Vue.js 的目标是通过尽可能简单的 API 实现响应的数据绑定和组合的视图组件。

vue单文件组件

<template>
  <pagetitle  title="vue入门" :sub-title="a"></pagetitle>
</template>
<script>
export default {
  mixins: [],
  comments: {
    // 引入局部组件
  },
  data() {
    return {
      a: ''
    }
  },
  computed: {
    // 计算属性 a 变了 newa 才变
     newa() {
        return a * 2;
      }
  },
  created(){
    // 页面初始化一些处理
    this.fetchData();
  },
  watch: {
    a(newVal, oldVal) {
      // a改变后触发
    }
  },
  methods: {
    fetchData() {
      //请求数据
    }
  }
}
</script>

模板数据绑定

<!-- 文本插值 -->
<span>Message: {{ msg }}</span>
<!-- 单次插值 -->
<span v-once>这个将不会改变: {{ msg }}</span>

<!-- 原始html -->
<span v-html="rawHtml"></span>

<!-- 特性 -->
<div v-bind:id="dynamicId"></div>
<button v-bind:disabled="isButtonDisabled">Button</button>

<!-- 表达式 -->
{{ number + 1 }}
{{ ok ? 'YES' : 'NO' }}
{{ message.split('').reverse().join('') }}
<div v-bind:id="'list-' + id"></div>


<!-- 过滤器 -->
{{ message | capitalize }}
<!-- 在 `v-bind` 中 -->
<div v-bind:id="rawId | formatId"></div>
<!-- 在双花括号中 -->
{{ message | capitalize }}
<!-- 在 `v-bind` 中 -->
<div v-bind:id="rawId | formatId"></div>

表单输入绑定

<input v-model="message" placeholder="edit me">
<p>Message is: {{ message }}</p>

更多参见:https://cn.vuejs.org/v2/guide...

computed 与 watch

<template>
  <div id="example">
      a={{a}}, b={{c}}, c={{c()}}
  </div>
</template>
<script>
  export default {
    data() {
      return {
        a: 1,
        d: 1
      }
    },
    computed: {
      // 一个计算属性的 getter
      b: function() {
        // this 指向实例
        return this.a + 1;
      },
      c: function() {
        return Data.now();
      },
      e: function() {
        return this.a + 2;
      }
    },
    watch: {
      a: function() {
        this.d = this.a + 2;
      }
    }
  }
</script>

样式 class与style绑定

class

<!-- 对象语法 -->
<div class="static"
  v-bind:class="{ 'class-a': isA, 'class-b': isB}"
>
</div>

<!-- 数组语法 -->
<div v-bind:class="[classA, classB]"></div>
<script type="text/javascript">
  data: {
    classA: 'class-a',
    classB: 'class-b'
  }
</script>

style

<!-- 对象语法 -->
<div v-bind:style="{ color: activeColor, fontSize: fontSize + 'px' }"></div>
<div v-bind:style="styleObject"></div>
<script>
   data: {
     styleObject: {
        color: 'red',
        fontSize: '13px'
     }
   }
</script>
<!-- 数组语法 -->
<div v-bind: style="[baseStyles, overridingStyles]"></div>

条件渲染

<!-- if -->
<h1 v-if="ok"> Yes </h1>

<!-- if else-->
<div v-if="Math.random() > 0.5">
  Now you see me
</div>
<div v-else>
  Now you don't
</div

<!-- if else v-else-if-->
div v-if="type === 'A'">
  A
</div>
<div v-else-if="type === 'B'">
  B
</div>
<div v-else-if="type === 'C'">
  C
</div>
<div v-else>
  Not A/B/C
</div>

<!-- template -->
<template v-if="ok">
  <h1>Title</h1>
  <p>Paragraph 1</p>
  <p>Paragraph 2</p>
</template>

<!-- v-show -->
<h1 v-show="ok">Hello!</h1>

列表渲染

<ul id="example-1">
  <li v-for="item in items">
    {{ item.message }}
  </li>
</ul>

var example1 = new Vue({  
   el: '#example-1',  
   data: {   
      items: [      
         { message: 'Foo' },      
         { message: 'Bar' }    
       ]  
  }})
在 v-for 块中,我们拥有对父作用域属性的完全访问权限。v-for 还支持一个可选的第二个参数为当前项的索引。
<ul id="example-2">
  <li v-for="(item, index) in items">
    {{ parentMessage }} - {{ index }} - {{ item.message }}
  </li>
</ul>

var example2 = new Vue({
  el: '#example-2',
  data: {
    parentMessage: 'Parent',
    items: [
      { message: 'Foo' },
      { message: 'Bar' }
    ]
  }
})

结果:
image

v-for 通过一个对象的属性来迭代。

<div v-for="(value, key, index) in object" :key="item.id">  {{ index }}. {{ key }}: {{ value }}</div>

new Vue({
  el: '#v-for-object',
  data: {
    object: {
      firstName: 'John',
      lastName: 'Doe',
      age: 30
    }
  }
})
建议尽可能在使用 v-for 时提供 key,除非遍历输出的 DOM 内容非常简单,或者是刻意依赖默认行为以获取性能上的提升。
结果:

image

更改检测

var vm = new Vue({
  data: {
    a: 1
  }
})
// `vm.a` 现在是响应式的
vm.b = 2
// `vm.b` 不是响应式的
对于已经创建的实例,Vue 不能动态添加根级别的响应式属性。但是,可以使用 Vue.set(object, key, value) 方法向嵌套对象添加响应式属性。例如,对于:
var vm = new Vue({
  data: {
    userProfile: {
      name: 'Anika'
    }
  }
})

可以添加一个新的 age 属性到嵌套的 userProfile 对象:

Vue.set(vm.userProfile, 'age', 27)

还可以使用 vm.$set 实例方法,它只是全局 Vue.set 的别名:

vm.$set(vm.userProfile, 'age', 27)

事件绑定

<template>
   <button v-on:click="greet">Greet</button>
   <!-- 简写 -->
  <button @click="greet">Greet</button>
  <!-- 内联 -->
  <button v-on:click="say('hi')" > Say hi </button>
  <!-- 阻止单击事件冒泡 -->
  <a v-on:click.stop="doThis"></a>
  <!-- 提交事件不再重载页面 -->
  <from v-on:submit.prevent="onSubmit"></from>
  <!-- 修饰符串联 -->
  <a v-on:click.stop.prevent="doThat"></a>
  <!-- 只有修饰符 -->
  <from v-on:submit.prevent></from>
  <!-- 添加事件侦听器时使用捕获模式 -->
  <div v-on:click.capture="doThis">...</div>
  <!-- 只当事件再该元素本身时才触发(比如不是子元素) 触发时触发回调-->
  <div v-on:click.self="doThat">...</div>
  <!-- 只有在keyCode 是 13 时调用 vm.submit() -->
  <input @key.enter="submit">
</template>
<script>
export default {
  data() {
     return {
       name: 'vue.js'
     }
   },
  methods: {
     greet: function(event) {
        alert('greet');
     },
     say: function(msg) {
         alert(message);
     }
  }
}
</script>

Mixins

// 定义一个混合对象
var myMixin = {
   created: function() {
      this.hello()
   },
   methods: {
      hello: function() {
         console.log('hello from mixin!')
      }
   }
}

// 定义一个组件, 使用这个混合对象
var Component = Vue.extend({
   mixins: [myMixin]
})

插件

image

MyPlugin.install = function (Vue, options) {
  // 1. 添加全局方法或属性
  Vue.myGlobalMethod = function () {
    // 逻辑...
  }
  // 2. 添加全局资源
  Vue.directive('my-directive', {
    bind (el, binding, vnode, oldVnode) {
      // 逻辑...
    }
    ...
  })
  // 3. 注入组件
  Vue.mixin({
    created: function () {
      // 逻辑...
    }
    ...
  })
  // 4. 添加实例方法
  Vue.prototype.$myMethod = function (methodOptions) {
    // 逻辑...
  }
}

注册组件

局部注册组件

<template>
  <my-component></my-component>
</template>
<script>
import MyComponent  from './myComponent';
export default {
  component: {
    // 局部注册
    MyComponent
  }
}
</script>

全局注册组件

// a.vue
<template>
   <my-component></my-component>
</template>

// myComponent.vue
<template>
   <div>my-component</div>
</template>

// main.js
import MyComponent from ./myComponent''
// 全局注册
Vue.component('my-component',  MyComponent);
// 创建根实例
new Vue({
   el: '#example'
})

Props

<child msg="hello!"></child>
// 动态props
<child :msg="hello!"></child>
// 双向绑定
<child :msg.sync="hello!"></child>
// 单次绑定
<child :msg.once="hello!"></child>
Vue.component('child', {
  // 声明 props
   props: ['msg'],
  // prop 可以在模板内
  // 可以用 `this.msg` 设置
  template: '<span> {{msg}}</span>'
})

slot

  <h2>我是子组件的标题</h2>
  <slot>
    只有在没有要分发的内容时才会显示。
  </slot>
</div>
// 父模板
<div>
  <h1>我是父组件的标题</h1>
  <my-component>
    <p>这是一些初始内容</p>
    <p>这是更多的初始内容</p>
  </my-component>
</div>
// 渲染结果
<div>  
  <h1>我是父组件的标题</h1>  
  <div>    
    <h2>我是子组件的标题</h2>    
    <p>这是一些初始内容</p>    
    <p>这是更多的初始内容</p>  
  </div>
</div>

具名插值

<div class="container">
  <header>
    <slot name="header"></slot>
  </header>
  <main>
    <slot></slot>
  </main>
  <footer>
    <slot name="footer"></slot>
  </footer>
</div>

答案在风中飘着
302 声望6 粉丝

\失去人性,失去许多!失去兽性,失去一切!