Vue2.0 - 启程

埋头在文档中,在记录,在整理,再没用过,从1.0起关注,至今,总算心怀忐忑,又有几分兴奋要准备将2.0用在项目中。此间必然有各种不知不解,此篇会将从项目中学到的点滴记录在内。

文档资源

vue组件

案例

  • vue2-elm:高仿饿了么
  • vue-dribbble:输出dribbble输出流,使用了 e81de24b7a2a57b7b1记录进行demo展示:
    • vue-router路由控制:router-view
    • vue-resource跨域请求:jsonp
    • vue-infinite-scroll:无限滚动插件(饿了么出品),从而进行数据请求展示

脚手架

整理

  • 如何实现 热重载( hot-reloading )
  • 是否可使用rollup替换webpack -- 优先级低
  • 官方已经不推荐使用 vue-resource了,而是 axios -- 待确认
  • 何时可以操作真正的DOM元素,测试是在mounted时,JSFiddle Demo
  • nextTick是真正更改值的时候:

  • vm.$mount,用于挂载一个实例,官网例子demo见Demo,注意点:

    • 直接new对象使用,会覆盖替换元素
    • 通过appendChild,可在原生DOM后添加实例
  • vue多页面模板

Vue报错

  • Do not use built-in or reserved HTML elements as component 原因:使用的组件名字同html默认标签名字一样

Vue两种写法

  • 常规页面写法 html部分:
<script src="https://unpkg.com/vue"></script>
<div id="app">
  <p>{{ message }}</p>
</div>

js部分:

new Vue({
  el: '#app',
  data: {
    message: 'Hello Vue.js!'
  }
})
  • Vue模板写法
<template lang="html">
    <div id="app">
        <img src="./assets/logo.png" alt="">
        <h1>{{ msg }}</h1>
        <h2>{{ subtit }}</h2>
    </div>
</template>

<script>
export default {
    data() {
        return {
            msg: 'Hello Vue!',
            subtit: 'Thanks your work.'
        }
    }
}
</script>

<style lang="css">
</style>

模板语法有两个注意点

  • 一个<template>组件下只能有一个div,其他div需要嵌套在里边
  • 数据要写在 return 里面而不是data: {message: 'Hello Vue.js!'}

插入组件方式

1.script中引入

import comp from './mycomp/path/comp.vue'
  1. 注册
export default {
    data () {
        return {
           msg: 'Hello Vue!'
        }
    },
    components: { comp }
}
  1. 使用
<template>
    <div id="app">
        <img src="./assets/logo.png">
        <h1>{{ msg }}</h1>
        <comp></comp>
    </div>
</template>

scoped - 局部css样式

When a tag has the scoped attribute, its CSS will apply to elements of the current component only. This is similar to the style encapsulation found in Shadow DOM. It comes with some caveats, but doesn't require any polyfills. It is achieved by using PostCSS to transform the following:

<style scoped>
.example {
  color: red;
}
</style>

<template>
  <div class="example">hi</div>
</template>

Into the following:

<style>
.example[data-v-f3f3eg9] {
  color: red;
}
</style>

<template>
  <div class="example" data-v-f3f3eg9>hi</div>
</template>

less 模块

根据论坛反馈,使用方式如下,未做测试:

  1. 安装依赖

    npm install --save less-loader
  2. 配置

    {
    test: /\.less$/,
    loader: "style!css!less"
    }
  3. 单vue组件文件,语言提示

    <style lang="less">
  4. main.js引入使用

    require('./mystyles.less')

    method,watch,及computed使用

ref使用

定义:

<div id="parent">
  <user-profile ref="profile"></user-profile>
</div>

访问:

var parent = new Vue({ el: '#parent' })
// 访问子组件
var child = parent.$refs.profile

页面闪烁

初次页面闪烁,办法两种:

  • 使用单模板文件组件(.vue),html 文件中仅插入组件标签
  • 使用v-cloak
# 样式文件
[v-cloak] {
    display:none
}

# html
<div v-cloak>{{ message }}</div>

v-bind

注: v-bind绑定的变量可以带引号,也可以不带引号
v-bind可以绑定的属性:

<!-- 绑定一个属性 -->
<img v-bind:src="imageSrc">

<!-- 缩写 -->
<img :src="imageSrc">

<!-- with inline string concatenation -->
<img :src="'/path/to/images/' + fileName">

<!-- class 绑定 -->
<div :class="{ red: isRed }"></div>
<div :class="[classA, classB]"></div>
<div :class="[classA, { classB: isB, classC: isC }]">

<!-- style 绑定 -->
<div :style="{ fontSize: size + 'px' }"></div>
<div :style="[styleObjectA, styleObjectB]"></div>

<!-- 绑定一个有属性的对象 -->
<div v-bind="{ id: someProp, 'other-attr': otherProp }"></div>

<!-- 通过 prop 修饰符绑定 DOM 属性 -->
<div v-bind:text-content.prop="text"></div>

<!-- prop 绑定. “prop” 必须在 my-component 中声明。 -->
<my-component :prop="someThing"></my-component>

<!-- XLink -->
<svg><a :xlink:special="foo"></a></svg>

# 绑定对象[demo链接](https://jsfiddle.net/onvno/mspejf3a/)
<div v-bind="json">
new Vue({
  el: '#app',
  data() {
    return {
      json: { 
        foo: 'a',
        bar: 'b',
        style: 'background: red',
        class: 'example'
      }
    }
  }
})

v-model官网

官网对v-model解释足够清楚,此处只为整理:
可以使用的类型

  • <input>,<textarea>文本输入框: v-model="msg"
  • <input type="checkbox">单个勾选框:v-model="checked"
  • <input type="checkbox">多个勾选框:v-model="checkedNames"
  • <input type="radio">单选按钮:v-model="picked"
  • <select><option>..单选/多选列表:v-model="selected"
  • 动态选项:<option v-for="option in options" v-bind:value="option.value">
  • components 修饰符
  • .lazy - 取代 input 监听 change 事件
  • .number - 输入字符串转为数字
  • .trim - 输入首尾空格过滤 v-bindv-model > 有时我们想绑定 value 到 Vue 实例的一个动态属性上,这时可以用 v-bind 实现,并且这个属性的值可以不是字符串。
<input
  type="checkbox"
  v-model="toggle"
  v-bind:true-value="a"
  v-bind:false-value="b"
>

// 当选中时
vm.toggle === vm.a
// 当没有选中时
vm.toggle === vm.b

组件prop注意点

在联系组件中,发现部分传值经常性反馈类似Expected Number, got Stringissue#1704
原因多为需要将字面量转为实际所需要的类型,需要更改为v-bind

如果想传递一个实际的number,需要使用 v-bind ,从而让它的值被当作 JavaScript 表达式计算

<!--引入自有组件-->
# error
<change autofocus="true"></change>

# true
<change :autofocus="true"></change>

slot内容分发

  • 单个slot > 除非子组件模板包含至少一个 插口,否则父组件的内容将会被丢弃。当子组件模板只有一个没有属性的 slot 时,父组件整个内容片段将插入到 slot 所在的 DOM 位置,并替换掉 slot 标签本身。 最初在 标签中的任何内容都被视为备用内容。备用内容在子组件的作用域内编译,并且只有在宿主元素为空,且没有要插入的内容时才显示备用内容。
  • 具名slot > 元素可以用一个特殊的属性 name 来配置如何分发内容。多个 slot 可以有不同的名字。具名 slot 将匹配内容片段中有对应 slot 特性的元素。 仍然可以有一个匿名 slot ,它是默认 slot ,作为找不到匹配的内容片段的备用插槽。如果没有默认的 slot ,这些找不到匹配的内容片段将被抛弃。
# 子组件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">这里可能是一个页面标题</h1>
  <p>主要内容的一个段落。</p>
  <p>另一个主要段落。</p>
  <p slot="footer">这里有一些联系信息</p>
</app-layout>

# 结果
<div class="container">
  <header>
    <h1>这里可能是一个页面标题</h1>
  </header>
  <main>
    <p>主要内容的一个段落。</p>
    <p>另一个主要段落。</p>
  </main>
  <footer>
    <p>这里有一些联系信息</p>
  </footer>
</div>

单组件文件vue使用内联组件Vue.component注册

此种情况使用默认vue会报如下错误:

[Vue warn]: You are using the runtime-only build of Vue where the template compiler is not available. Either pre-compile the templates into render functions, or use the compiler-included build.
根据错误提示,查询依赖包vue有多个版本vue.x.js文件,其比较如下:

UMD CommonJS ES Module
Full vue.js vue.common.js vue.esm.js
Runtime-only vue.runtime.js vue.runtime.common.js vue.runtime.esm.js
Full (production) vue.min.js
Runtime-only (production) vue.runtime.min.js

只需要将webpack配置文件,更改为:

'vue$': 'vue/dist/vue.js'

vue组件命名及使用

事情这样:查看一组件hsy-vue-dialog源码中,将组件命名为name: 'HsyDialog',但在使用时名称为hsy-dialog,遂造成一万点伤害。然后查询得到结果:
聊聊 Vue 组件命名那些事

通过标签名寻找对应的自定义组件。匹配的优先顺序从高到低为:原标签名、camelCase化的标签名、PascalCase化的标签名。例如 会依次匹配 my-component、myComponent、MyComponent。
遂自己测试一列:

# 单页面结构为:app.html, app.vue, app.js

# app.js
Vue.component('MyComp', {
  template: '<div>A custom component!</div>'
})

# app.vue中使用组件
<!-- 引入内建组件  -->
<my-comp></my-comp>

测试结果正常显示,验证此问题。

单文件组件-父子组件通信

通过props传值

# 父页面app.vue
<template>
  <div id="app">
    <img src="./assets/logo.png">
    <hello mes-father="message from father"></hello>
  </div>
</template>

# 子页面
<template>
  <div class="hello">
    <p>{{mesFather}}</p>
  </div>
</template>

<script>
export default {
  props:['mesFather']
}
</script>

子组件传值给父组件

子组件通过methods方法传值给父组件,如需要传参数,可按照以下示例:

# 子组件
var data = {
    a:11,
    b:22
}
this.$emit("senddata", data);

# 父组件
<test v-on:senddata="getData"></test>
methods: {
        getData:function(data){
            console.log("子组件传递的数据:",data);
        }
    }

vue监听对象级的props

Vue.js - How to properly watch for nested properties

# 子组件
props:[item],
watch{
  item: {
     handler(val){
       // do stuff
     },
     deep: true
  }
}

参考链接

@2017-05-16 22:27