当前位置: 首页 > article >正文

Vue2:脚手架 vue-cli

Vue2:脚手架 vue-cli

    • 结构
    • render
    • ref
    • props
    • mixin
    • scoped


脚手架是Vue官方提供的Vue开发平台,.vue文件就需要通过脚手架来解析,所以对于单文件组件就依赖于脚手架。

安装:

npm i -g @vue/cli

如果执行vue --version有输出,那么说明脚手架安装成功了。

基于脚手架,可以快速创建一个项目的基本结构,命令如下:

vue create 项目名

创建一个名为study的项目:

在这里插入图片描述

此时会询问,要使用哪一个Vue版本,目前使用Vue2

出现以下界面,说明脚手架创建成功:

在这里插入图片描述

进入项目目录,执行:

npm run serve

此时基于现有的.vue文件,启动一个本地服务,随后就可以通过本地服务访问页面:

在这里插入图片描述

访问127.0.0.1:8080

在这里插入图片描述

此时Vue脚手架就已经开始运行了,这个页面是创建脚手架时Vue自动创建的一个hello界面。


结构

脚手架初始的文件结构如下:

├── node_modules 
├── public
│   ├── favicon.ico: 页签图标
│   └── index.html: 主页面
├── src
│   ├── assets: 存放静态资源
│   │   └── logo.png
│   │── component: 存放组件
│   │   └── HelloWorld.vue
│   │── App.vue: 汇总所有组件
│   │── main.js: 入口文件
├── .gitignore: git版本管制忽略的配置
├── babel.config.js: babel的配置文件
├── package.json: 应用包配置文件 
├── README.md: 应用描述文件
├── package-lock.json:包版本控制文件
  1. public/index.html:主页文件,引入src/main.js作为入口
  2. src/main.js:定义了最大的vm对象,引入App.vue管理App组件
  3. src/App.vue:最大的组件,所有的组件都在该组件之下统一管理
  4. src/component/:该目录下是所有的组件

简单来说,所有的组件都定义在src/component/目录下,并被App.vue统一管理,最后经过src/main.js引入到public/index.html主页中,这样就构成了一个页面。

程序员的绝大部分操作,都在src/component/目录中。


render

打开main.js,内容如下:

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

Vue.config.productionTip = false

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

刚才提到,main.js负责引入App.vue但是这一块的语法非常奇怪,使用了一个render方法。

正常来说,引入App.vue应该这样写:

new Vue({
  el:'#app',
  template: `<App></App>`,
  components: {App}
})

通过components引入App组件,再通过template模板解析<App>标签,但是这样是错误的。

因为vue-cli默认引入的是一个简化版本的vue,这个版本没有模板解析器,在vm中没有template选项,所以以上代码无法运行。

render方法可以向网页中添加一个DOM节点:

new Vue({
  el:'#app',
  render(createElement){
  	return createElement('标签', '内容')
	}
})

render接收一个参数createElement,该参数是一个函数,函数的第一个参数传入标签名,第二个参数传入内容。这样就可以在网页中渲染出一个DOM节点,比如创建一个<h1> hello </h1>

new Vue({
  el:'#app',
  render(createElement){
  	return createElement('h1', 'hello')
	}
})

由于最后要使用App标签,由不能通过模板解析器,此时就可以借助于render

render(createElement){
 	return createElement(App)
}

App中无需传入内容,所以createElement就没有第二个参数。以上写法可以进行简化:

// 简化参数名称
render(h){
 	return h(App)
}

// 变为箭头函数
render: h => h(App)

这样就变为了main.js中的形态,最后把el: '#app'改为$mount的形式,就得到:

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

ref

ref是一个标签属性,其可以快速拿到一个标签的DOM对象,如果标签是组件,那么可以得到该组件的实例对象。

当前App.vue结构如下:

<template>
  <div id="app">
    <h2>一个标题</h2>
    <HelloWorld/>
  </div>
</template>

其包含一个标题h2和一个组件HelloWorld,对这两个标签添加ref属性:

<template>
  <div id="app">
    <h2 ref="title">一个标题</h2>
    <HelloWorld ref="hello" />
    <button @click="testRef"></button>
  </div>
</template>

最后在methods中添加一个testRef方法,输出当前的vm

export default {
  name: 'App',
  components: {
    HelloWorld
  },
  methods:{
    testRef(){
      console.log(this)
    }
  }
}

点击按钮输出结果:

在这里插入图片描述

vm下,多出一个$ref属性,该属性有hellotitle两个子属性,其中helloVueComponent对象,也就是一个组件的实例,而title<h2>标签的DOM对象。

基于ref方法,可以快速的获取到指定标签的DOM对象或者vc对象,这在组件间通信时有很大的用处。

console.log(this.$refs.title)
console.log(this.$refs.hello)

输出结果:

在这里插入图片描述


props

props可以让组件接收外部传入的数据。

现有一个StudentInfo组件,结构如下:

<template>
    <div>
        <h2>学生信息:</h2>
        <p>姓名:</p>
        <p>年龄:</p>
        <p>性别:</p>
    </div>
</template>

App.vue中引入该组件,那么如何才能让StudentInfo组件输出不同的学生信息?这就需要使用props属性了。

语法:

{
    props:['属性1','属性2',...]
}

在配置项中,peops配置项可以接收来自外部的参数,将要接受的属性名以数组形式写在props中。

修改StudentInfo.vue

<template>
    <div>
        <h2>学生信息:</h2>
        <p>姓名:{{ name }}</p>
        <p>年龄:{{ age }}</p>
        <p>性别:{{ sex }}</p>
    </div>
</template>

<script>
export default {
    name: 'StudentInfo',
    props:['name', 'age', 'sex']
}
</script>

App.vue中,只需要使用组件标签时,把参数以属性的形式传入即可:

<template>
  <div id="app">
    <StudentInfo name="张三" age="18" sex="男"/>
    <StudentInfo name="翠花" age="22" sex="女"/>
  </div>
</template>

输出结果:

在这里插入图片描述

这样同一个组件就可以接收父组件的参数,承载不同的信息了。

props还有更加详细的传参方式:

props:{
     name: String,
     age: Number,
     sex: String
 }

props定义为对象,组件接收的每个参数可以指定接收类型,这样可以完成对数据类型的限制。

默认情况下,属性传入的都是字符串:

<StudentInfo name="张三" age="18" sex=""/>

以上传入的三个参数都是字符串,包括18也是字符串。如果传参时希望解析内容,而不是字符串,就需要通过:单向绑定,这样会把""内部的内容作为表达式解析。其中age要以数字的形式传入,所以加上:修饰。

<StudentInfo name="张三" :age="18" sex=""/>

StudentInfo组件中,输出age+1

<template>
    <div>
        <h2>学生信息:</h2>
        <p>姓名:{{ name }}</p>
        <p>年龄:{{ age + 1 }}</p>
        <p>性别:{{ sex }}</p>
    </div>
</template>

输出结果:

在这里插入图片描述

加法正常执行了,说明传入的18成功解析为了字符串。

此处可以得到两个要点:

  1. 传参时如果数据类型不是字符串,要加上:修饰,将内容作为表达式解析
  2. 接收方可以在props内部限定传入数据的类型

props还有更详细的写法:

props{
	'属性':{
		type:Number,
		required:false,
		default:20
	}
}
  • type:限定该属性的类型
  • required:该属性是否可以缺省
  • default:如果不传参,该属性的缺省值

如果外界没有传入某个属性,并且这个属性没有缺省值,那么默认为undefined


mixin

现有StudentInfoTeacherInfo两个组件,如下:

  • TeacherInfo
export default {
    name: 'TeacherInfo',
    data(){
        return {
            name: '李老师',
            classRoom: "三班 四班"
        }
    },
    methods:{
        getName() {
            console.log(this.name)
        }
    }
}
  • StudentInfo
export default {
    name: 'StudentInfo',
    data(){
        return {
            name: '张三',
            age: 18,
            sex: '男'
        }
    },
    methods:{
        getName() {
            console.log(this.name)
        }
    }
}

在这两个组件中,有一个getName方法都是一样的,那么mixin就可以处理这样的多个组件之间,存在相同属性或方法的复用问题。

.js文件内部的属性和方法,可以通过mixin添加到多个组件中,这样多个组件就可以复用相同的属性和方法。

  • test.js
export const test = {
    methods:{
        getName() {
            console.log(this.name)
        }
    }
}

test.js中,把getName方法定义到一个对象下,并把对象暴露出去。

接下来就可以在组件中引入这个test.js,并通过mixin使用test.js内的方法:

import {test} from '../test.js'

export default {
    name: 'TeacherInfo',
    data(){
        return {
            name: '李老师',
            classRoom: "三班 四班"
        }
    },
    mixins:[test]
}

通过mixin引入,需要通过mixins配置项,值为一个数组,数组内部是要导入的对象。

随后在TeacherInfo中就可以使用test.js内部的方法了,StudentInfo同理。

除此之外,mixin引入的.js文件中,还可以定义data数据、hook生命周期钩子等等内容:

export const test = {
    data(){
        return {
            a: 1,
            b: 2
        }
    },
    methods:{
        getName() {
            console.log(this.name)
        }
    },
    mounted(){
        console.log("挂载完成")
    }
}

任何通过mixin引入这个test的组件,都会获得test内部的所有内容,这样就可以把不同组件内部相同的内容,通过mixin进行复用。


scoped

依然沿用之前的TeacherInfoStudentInfo结构,但是分别为它们添加背景色的样式:

  • TeacherInfo
<style>
    p{
        background-color: pink;
    }
</style>
  • StudentInfo
<style>
    p{
        background-color: skyblue;
    }
</style>

两个组件分别使用的了不同的背景色,都作用于<p>标签,输出结果:

在这里插入图片描述

输出时,它们都变成了粉色,可是学生信息明明是skyblue,为什么变成了粉色?

这是因为在.vue进行汇总时,会把所有组件的<style>都放到一起,导致<p>标签的样式之间发生了覆盖。

App.vue中引入组件:

import StudentInfo from './components/StudentInfo.vue'
import TeacherInfo from './components/TeacherInfo.vue'

TeacherInfo是后引入的,所以会覆盖掉StudentInfo<p>样式,导致学生样式输出错误。

如果要解决这个问题,就需要scoped属性,其可以限定<style>内部的样式,只作用于当前的组件,不会影响其它的组件。

语法:

<style scoped>
<style>

现在给两个组件的<style>都加上这个属性:

在这里插入图片描述

css样式分别独立了,大部分情况下,为了避免组件之间样式相互影响,都会启用这个属性。



http://www.kler.cn/a/395312.html

相关文章:

  • 【鸿蒙开发】第十一章 Stage模型应用组件-任务Mission
  • mysql每日一题(上升的温度,date数据的计算)
  • vite + vue3 + ts解决别名引用@/api/user报错找不到相应的模块
  • 122、java的LambdaQueryWapper的条件拼接实现数据sql中and (column1 =1 or column1 is null)
  • Linux 下 mysql 9.1 安装设置初始密码 【附脚本】
  • 轮转数组
  • UDP/TCP 简述
  • Elasticsearch集群和Kibana部署流程
  • 【OceanBase 诊断调优】—— OceanBase 数据库统计信息被禁用,状态为 broken 的原因和解决方法
  • 【论文阅读】Virtual Compiler Is All You Need For Assembly Code Search
  • 数位DP学习
  • 人工智能:重塑医疗、企业与生活的未来知识管理——以HelpLook为例
  • 【数字图像处理+MATLAB】基于 Sobel 算子计算图像梯度并进行边缘增强:使用 imgradientxy 函数
  • 《Java核心技术 卷I》Swing处理2D图形
  • 探索 Python HTTP 的瑞士军刀:Requests 库
  • JavaScript逆向爬虫教程-------基础篇之深入JavaScript运行原理以及内存管理
  • openwebui二改界面环境搭建
  • Ubuntu网络(prot)连通性检测
  • 当使用key-value方式进行参数传递时,若key对应的是一个对象或数组结构,如何利用API Post工具进行模拟操作。
  • thinkphp6 --数据库操作 增删改查
  • Flutter:使用Future发送网络请求
  • unity3d————插值运算补充点
  • 使用 Spring Security 实现基于角色的权限管理
  • ssm111基于MVC的舞蹈网站的设计与实现+vue(论文+源码)_kaic
  • C#笔记(3)
  • 解决Spring Boot整合Redis时的连接问题