Vue单文件组件的开发以及CLI脚手架的使用

Vue.component全局注册组件的方式的缺点

Vue.component方式 定义的全局组件很方便,但是它有几个天生的缺陷,导致它只能用在很小的项目中,无法发挥Vue框架的全部实力。

  • 它是全局自定义的,要求组件的名称全局唯一,组件数量一旦较多就很难管理。
  • 它没有办法被编辑器的语法高亮支持,编写复杂的template时比较麻烦。
  • 它不支持CSS,需要在外部定义组件的样式,影响组件的使用效率。
  • 它不支持动态构建,无法使用预处理和热加载。
Vue的单文件组件解决方案及其环境安装和配置

Vue框架给出的解决方案时.vue后缀的单文件组件。
那么如何使用.vue为后缀的单文件组件来享受Vue提供给我们的这些便利呢?

  1. 首先,需要安装node.js框架,通过安装这个框架,我们可以获得一系列自动化的工具如npm,当然也可以自行安装yarn来作为npm的替代。但是node.js是一定要安装的。
  2. 安装完毕node.js之后,我们通过npm命令安装vue脚手架.-g是指将vue脚手架安装到全局用户。
npm install -g @vue/cli
  1. 安装完成之后,可以通过vue命令查看安装是否成功以及安装的vue版本
vue --version

如图

image
4. 接下来,我们就可以通过vue的create指令创建新的前端vue工程。并选择default模式。然后脚手架会自动安装工程需要的全部依赖

vue create vue-demo
  1. 创建完成后的vue-demo工程会存在于用户文件夹下的当前用户下。可以看到脚手架帮助我们创建了很多基础文件,甚至为我们创建了本地git。
    如图:
    image

  2. 在控制台中通过cd进入这个目录文件夹,然后通过npm或yarn命令启动项目。推荐使用yarn方式。

npm run serve

image
或者

yarn serve

image

7.此时已经可以访问创建的vue-demo了
image

现有组件的单文件化改造

为了进一步深入学习,接下来,我们要把前面一直在优化的todo-list和todo-item组件改造成Vue单文件组件,并使用前端框架的形式访问。

  1. 打开vue-demo前端项目的入口文件main.js,这个文件中定义了vue的根节点名称。
new Vue({
  render: h => h(App),
}).$mount('#app')

起到的作用类似于

var vm = new Vue({
        el: "#app",
        /.../
        })
  1. render:h=>h(App)代表入口组件是App.vue,我们需要在App.vue引入并注册todo-list和todo-item组件。
  2. App.vue默认引用并注册了一个叫HelloWorld的组件。从这个示例证明,要想在App.vue中引入我们自己的组件,我们先要为这两个组件创建自己的单文件.vue文件。
    image
  3. 按照约定,我们在components文件夹在创建两个vue后缀文件。
  4. 首先是todo-item.vue。通过观察helloWorld.vue,我们可以发现,一个vue文件是由三大块组成的。
  • template用来放置模板,相当于现有组件中的template标签。
  • script用来放置组件的数据(data),方法(methods),属性(props)
  • style是原有组件中不予支持的样式表
<template>
    
</template>
<script>
export default {
    
}
</script>
<style scoped>

</style>
  1. 按照这个结构,我们需要将原有todo-item组件下的template部分,放置到template标签中
template: `
              <li>
                  <slot name="pretext" :val="vrandom"></slot>
                  <span v-if="!del">{{title}}</span>
                  <span v-else style="text-decoration:line-through">{{title}}</span>
                  <button v-show="!del" @click="handleClick">删除</button>
                  <slot name="suftext">默认尾部</slot>
              </li>`,

变为

<template>
    <li>
        <slot name="pretext" :val="vrandom"></slot>
        <span v-if="!del">{{title}}</span>
        <span v-else style="text-decoration:line-through">{{title}}</span>
        <button v-show="!del" @click="handleClick">删除</button>
        <slot name="suftext">默认尾部</slot>
    </li>
</template>
  1. 将原组件中的props,data,methods放置到script标签中。
<script>
export default {
    props: {
          title: String,
          del: {
            type: Boolean,
            default: false
          }
        },
    data: function() {
          return {
              vrandom:Math.random()
          };
        },
    methods: {
            handleClick(){
                console.log("点击删除按钮!");
                this.$emit('delete',this.title);
            }
        }
}
</script>
  1. 同理,我们创建todo-list.vue
<template>
    <ul>
        <slot></slot>
    </ul>
</template>
<script>
export default {
    data: function() {
          return {
            
          };
        },
    methods:{
            
    }
}
</script>
<style scoped>

</style>

9.在App.vue将todo-item.vue和todo-list.vue引入并注册.

<script>
import todolist from './components/todo-list.vue'
import todoitem from './components/todo-item.vue'

export default {
  name: 'App',
  components: {
    todolist,
    todoitem
  }
}
</script>
  1. 我们注册了todolist和todoitem,我们需要在App.vue中使用它。要使用这两个组件,我们需要准备相应的数据。将原new Vue中的data数据和methods方法移到App.vue中。
    App.vue的完整script如下
<script>
import todolist from './components/todo-list.vue'
import todoitem from './components/todo-item.vue'

export default {
  name: 'App',
  components: {
    todolist,
    todoitem
  },
  data(){
    return{
      list: [
              {
                title: "新课程1",
                del: false
              },
              {
                title: "新课程2",
                del: true
              },
              {
                title: "新课程3",
                del: false
              }
            ]
    };
  },
  methods: {
    handleDelete(vtitle){
      console.log("删除工程!",vtitle)
    }
  }
}
</script>
  1. 最后将原页面中html代码,即使用todo-list和todo-item组件的html移至App.vue中。
<template>
  <div id="app">
    <todolist>
      <todoitem v-on:delete="handleDelete" v-for="item in list" data-wen="wen" :title="item.title" :del="item.del">
        <template v-slot:pretext="{val}">
          <label>前置文字{{val}}</label>
        </template>
      </todoitem>
    </todolist>
  </div>
</template>

此时有两个细节需要处理:

  • v-for 后面需要动态绑定Key关键字。
  • 使用的组件名要与注册的组件名一致。前期我们的组件一直叫todo-item,但是我们在本次注册时将组件注册为了todoitem,那么同理我们需要在使用时将名称对应起来。否则会报如下错误。
    image
  1. 全部完成后,效果如图
    image

至此,我们就完成了两个组件的单文件话改造。现在注册到App.vue的组件todolist和todoitem都是局部作用域,不会污染和与其他组件冲突。

那么,假如我们希望将todolist在全局注册怎么做能?
我们只需要在main.js中引入todolist并通过Vue.component注册即可。

import todolist from './components/todolist.vue'

Vue.component("todolist", todolist);

import Vue from 'vue'
import App from './App.vue'
import todolist from './components/todolist.vue'

Vue.component("todolist", todolist);

Vue.config.productionTip = false

new Vue({
  render: h => h(App),
}).$mount('#app')

但是一般建议少注册全局组件。

单文件组件中的样式的使用

单文件组件中我们还有一个内容一直没有使用:style,我们可以通过style定义自己组件的样式,并且保证这个样式只会对自己起作用而不污染其他组件。
写法如下:

<style scoped>
    .redsapn{color: red}
</style>

通过写在scoped标签,Vue框架会对我们的样式生成一个唯一哈希值,保证样式的唯一。
譬如,我们为todoitem组件增加上述样式,并在组件的template中使用:

<template>
    <li>
        <slot name="pretext" :val="vrandom"></slot>
        <span class="redsapn" v-if="!del">{{title}}</span>
        <span v-else style="text-decoration:line-through">{{title}}</span>
        <button v-show="!del" @click="handleClick">删除</button>
        <slot name="suftext">默认尾部</slot>
    </li>
</template>

执行效果如下:
image

posted @ 2020-02-08 17:35  文鹏  阅读(379)  评论(0编辑  收藏  举报