Vue-CLI

创建脚手架

1
2
1. 如出现下载缓慢请配置 npm 淘宝镜像:
npm config set registry https://registry.npm.taobao.org

脚手架官网https://cli.vuejs.org/zh/
具体步骤:
第一步(仅第一次执行):全局安装@vue/cli。

1
2
3
4
# 如果安装过了, 需要先卸载再次安装
# 卸载命令
# npm uninstall -g vue-cli
npm install -g @vue/cli

第二步:切换到你要创建项目的目录,然后使用命令创建项目

如果普通用户cmd无法创建, 使用管理员cmd试试

1
vue create xxxx

第三步:启动项目

1
npm run serve


访问http://localhost:8080/, 可以看见脚手架为我们默认创建一个 HelloWorld 组件

脚手架文件结构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
├── 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:包版本控制文件

脚手架运行项目的报错

xxx should always be multi-word vue/multi-word-component-names 报错
修改 vue.config.js 文件

1
2
3
4
5
const { defineConfig } = require("@vue/cli-service");
module.exports = defineConfig({
transpileDependencies: true,
lintOnSave: false, // 关闭语法检查(代码检查)
});

如果编写了代码, 左侧行数会出现一个红色小箭头, 这是 git 在记录


可以按 Ctrl+, 打开设置, 搜索 git:Enabled, 关闭 Git

部署自己的项目到脚手架


School.vue

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<template>
 
<div>
   
<h2>学校名称: {{ name }}</h2>
   
<h2>学校地址: {{ address }}</h2>
    <button @click="showName">点我显示名称</button>  
</div>
</template>

<script>
export default {
name: "School",
data() {
return {
name: "尚硅谷",
address: "北京",
};
},
methods: {
showName() {
alert(this.name);
},
},
};
</script>

<style></style>

Student.vue

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<template>
 
<div>
   
<h2>学生姓名: {{ name }}</h2>
   
<h2>学生年龄: {{ age }}</h2>
 
</div>
</template>

<script>
export default {
name: "Student",
data() {
return {
name: "肉豆蔻",
age: 18,
};
},
};
</script>

<style></style>

App.vue

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<template>
 
<div>    <School></School>     <Student></Student>  </div>
</template>

<script>
import Student from "./components/Student.vue";
import School from "./components/School.vue";

export default {
name: "App",
components: {
Student,
School,
},
};
</script>

<style></style>

main.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
/* 
该文件是整个项目的入口文件
*/
//引入Vue
import Vue from "vue";
//引入App组件, 它是所有组件的父组件
import App from "./App.vue";

//关闭Vue的生产提示
Vue.config.productionTip = false;

/*
关于不同版本的Vue:

1.vue.js与vue.runtime.xxx.js的区别:
(1).vue.js是完整版的Vue,包含:核心功能+模板解析器。
(2).vue.runtime.xxx.js是运行版的Vue,只包含:核心功能;没有模板解析器。

2.因为vue.runtime.xxx.js没有模板解析器,所以不能使用template配置项,需要使用
render函数接收到的createElement函数去指定具体内容。
*/

//创建vm
new Vue({
el: "#app",
//
render: (h) => h(App),

// render(createElement) {
// return createElement('h1', '你好啊')
// }

// template: `
// <h1>你好啊</h1>
// `,
// components: {
// app
// }
});

import Vue from ‘vue’中引入的是 vue 文件夹, 它是由 vue 文件夹中的 module 配置项来决定导入的是哪一个 vue.js
runtime.js 相比于 vue.js, 精简了模板解析器, 模板解析器也不会在 webpack 打包的时候被打包进去

关于不同版本的 Vue

  1. vue.js 与 vue.runtime.xxx.js 的区别:
    1. vue.js 是完整版的 Vue,包含:核心功能 + 模板解析器。
    2. vue.runtime.xxx.js 是运行版的 Vue,只包含:核心功能;没有模板解析器。
  2. 因为 vue.runtime.xxx.js 没有模板解析器,所以不能使用 template 这个配置项,需要使用 render 函数接收到的 createElement 函数去指定具体内容。

render 函数

使用 render 渲染函数就可以在 runtime.js 的环境中解析模板, template 在 runtime.js 的环境中没法解析模板, 因为 runtime 剔除了模板引擎

1
2
3
4
5
6
7
8
9
10
11
12
13
// render: h => h(App),

// render(createElement) {
// return createElement('h1', '你好啊')
// }

// render: function(createElement) {
// return createElement('h1', '你好啊')
// }

// render:(createElement) => createElement('h1', '你好啊')

render: (a) => a("h1", "你好啊");

修改默认配置(vue.config.js 配置文件)

vue.config.js
在 pages 选项中配置的 entry 可以指明 main.js 作为程序的入口, 当然可以设置成其他的, 一般保持默认既可

1
2
3
4
5
6
7
8
9
10
11
const { defineConfig } = require("@vue/cli-service");
module.exports = defineConfig({
pages: {
index: {
// 配置入口
entry: "src/main.js",
},
},
transpileDependencies: true,
lintOnSave: false,
});
  1. 使用 vue inspect > output.js 可以查看到 Vue 脚手架的默认配置。
  2. 使用 vue.config.js 可以对脚手架进行个性化定制,详情见:https://cli.vuejs.org/zh

ref 属性

  1. 被用来给元素或子组件注册引用信息(id 的替代者)
  2. 应用在 html 标签上获取的是真实 DOM 元素,应用在组件标签上是组件实例对象(vc)
  3. 使用方式:
    1. 打标识:

      …..

    2. 获取:this.$refs.xxx

Student.vue

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<template>
 
<div class="school">
   
<h2>学校名称:{{ name }}</h2>
   
<h2>学校地址:{{ address }}</h2>
 
</div>
</template>

<script>
export default {
name: "School",
data() {
return {
name: "尚硅谷",
address: "北京·昌平",
};
},
};
</script>

<style>
  .school{
    background-color: gray;
  }
</style>

App.vue

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<template>
 
<div>
   
<h1 v-text="msg" ref="title"></h1>
    <button ref="btn" @click="showDOM">点我输出上方的DOM元素</button>    
<School ref="sch" />  
</div>
</template>

<script>
//引入School组件
import School from "./components/School";

export default {
name: "App",
components: { School },
data() {
return {
msg: "欢迎学习Vue!",
};
},
methods: {
showDOM() {
console.log(this.$refs.title); //真实DOM元素
console.log(this.$refs.btn); //真实DOM元素
console.log(this.$refs.sch); //School组件的实例对象(vc)
},
},
};
</script>

props 配置

  1. 功能:让组件接收外部传过来的数据
  2. 传递数据:<Demo name="xxx"/>
  3. 接收数据:
  4. 第一种方式(只接收):props:['name']
  5. 第二种方式(限制类型):props:{name:String}
  6. 第三种方式(限制类型、限制必要性、指定默认值):
1
2
3
4
5
6
7
props:{
name:{
type:String, //类型
required:true, //必要性
default:'老王' //默认值
}
}

备注:props 是只读的,Vue 底层会监测你对 props 的修改,如果进行了修改,就会发出警告,若业务需求确实需要修改,那么请复制 props 的内容到 data 中一份,然后去修改 data 中的数据。

Student.vue

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
<template>
 
<div>
   
<h1>{{ msg }}</h1>
   
<h2>学生姓名: {{ name }}</h2>
   
<h2>学生性别: {{ sex }}</h2>
   
<h2>学生年龄: {{ MyAge + 1 }}</h2>
    <button @click="updateAge">点我修改年龄</button>  
</div>
</template>

<script>
export default {
name: "Student",
data() {
return {
msg: "我是一个尚硅谷的学生",
MyAge: this.age,
};
},
methods: {
updateAge() {
this.MyAge++;
},
}, //简单声明接收 // props: ['name', 'sex', 'age'] //接收的同时对数据进行类型限制 // props: { //   name: String, //   sex: String, //   age: Number // } //接收的同时对数据:进行类型限制+默认值的指定+必要性的限制
props: {
name: {
type: String, //name的类型是字符串
required: true, //name是必要的
},
sex: {
type: String,
default: "男", //默认值
},
age: {
type: Number,
default: 20,
},
},
};
</script>

App.vue

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<template>
 
<div>    <Student :age="18" name="尚硅谷" sex="男" />  </div>
</template>

<script>
import Student from "./components/Student.vue";
export default {
name: "App",
components: {
Student,
},
};
</script>

<style></style>

mixin 混入

  1. 功能:可以把多个组件共用的配置提取成一个混入对象
  2. 使用方式:
    第一步定义混合:
1
2
3
4
5
{
data(){....},
methods:{....}
....
}

第二步使用混入:
全局混入:Vue.mixin(xxx)
局部混入:mixins:['xxx']
School.vue

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<template>
 
<div>
   
<h2 @click="showName">学校名称: {{ name }}</h2>
   
<h2>学校地址: {{ address }}</h2>
 
</div>
</template>

<script>
// import {mixin} from "../mixin"
export default {
name: "School",
data() {
return {
name: "尚硅谷",
address: "北京",
};
}, // mixins: [mixin]
};
</script>

Student.vue

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<template>
 
<div>
   
<h2 @click="showName">学生姓名: {{ name }}</h2>
   
<h2>学生性别: {{ sex }}</h2>
 
</div>
</template>

<script>
// import {mixin} from "../mixin"
export default {
name: "Student",
data() {
return {
name: "张三",
sex: "男",
};
}, // mixins: [mixin],
mounted() {
// console.log("你好啊!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
},
};
</script>

App.vue

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<template>
 
<div>
    <Student />    
<hr />
    <School />  
</div>
</template>

<script>
import Student from "./components/Student.vue";
import School from "./components/School.vue";

export default {
name: "App",
components: {
Student,
School,
},
};
</script>

<style></style>

mixin.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
export const mixin = {
methods: {
showName() {
alert(this.name);
},
},
mounted() {
// console.log('你好啊!')
},
};

export const mixin2 = {
data() {
return {
x: 999,
y: 666,
};
},
};

main.js

1
2
3
4
5
6
7
8
9
10
11
12
import Vue from "vue";
import App from "./App";

import { mixin, mixin2 } from "./mixin";
Vue.config.productionTip = false;
Vue.mixin(mixin);
Vue.mixin(mixin2);

new Vue({
el: "#app",
render: (h) => h(App),
});

插件

  1. 功能:用于增强 Vue
  2. 本质:包含 install 方法的一个对象,install 的第一个参数是 Vue,第二个以后的参数是插件使用者传递的数据。
  3. 定义插件:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
对象.install = function (Vue, options) {
// 1. 添加全局过滤器
Vue.filter(....)

// 2. 添加全局指令
Vue.directive(....)

// 3. 配置全局混入(合)
Vue.mixin(....)

// 4. 添加实例方法
Vue.prototype.$myMethod = function () {...}
Vue.prototype.$myProperty = xxxx
}
  1. 使用插件:Vue.use()

Student.vue

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<template>
 
<div>
   
<h2>学生姓名: {{ name }}</h2>
   
<h2>学生性别: {{ sex }}</h2>
        <input type="text" v-fbind:value="name" />  
</div>
</template>

<script>
export default {
name: "Student",
data() {
return {
name: "张三",
sex: "男",
};
},
};
</script>

School.vue

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<template>
 
<div>
   
<h2 @click="test">学校名称: {{ name | mySlice }}</h2>
   
<h2>学校地址: {{ address }}</h2>
 
</div>
</template>

<script>
export default {
name: "School",
data() {
return {
name: "尚硅谷atguigu",
address: "北京",
};
},
methods: {
test() {
this.hello();
},
},
};
</script>

App.vue

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<template>
 
<div>
    <Student />    
<hr />
    <School />  
</div>
</template>

<script>
import Student from "./components/Student.vue";
import School from "./components/School.vue";

export default {
name: "App",
components: {
Student,
School,
},
};
</script>

<style></style>

main.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import Vue from "vue";
import App from "./App.vue";
// 引入插件
import plugins from "./plugins";

// 应用(使用)插件
Vue.use(plugins, 1, 2, 3);

Vue.config.productionTip = false;

new Vue({
el: "#app",
render: (h) => h(App),
});

plugins.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
export default {
install(Vue, x, y, z) {
console.log(x, y, z); // 全局过滤器
Vue.filter("mySlice", function (value) {
return value.slice(0, 4);
}); //定义全局指令

Vue.directive("fbind", {
//指令与元素成功绑定时(一上来)
bind(element, binding) {
element.value = binding.value;
}, //指令所在元素被插入页面时
inserted(element, binding) {
element.focus();
}, //指令所在的模板被重新解析时
update(element, binding) {
element.value = binding.value;
},
}); //定义混入

Vue.mixin({
data() {
return {
x: 100,
y: 200,
};
},
}); //给Vue原型上添加一个方法(vm和vc就都能用了)

Vue.prototype.hello = () => {
alert("你好啊");
};
},
};

scoped 样式

  1. 作用:让样式在局部生效,防止冲突。
  2. 写法:<style scoped>

School.vue

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<template>
 
<div class="demo">
   
<h2 class="title">学校名称: {{ name }}</h2>
   
<h2>学校地址: {{ address }}</h2>
 
</div>
</template>

<script>
export default {
name: "School",
data() {
return {
name: "尚硅谷atguigu",
address: "北京",
};
},
};
</script>

<style scoped>
  .demo {
    background-color: lightpink;
  }
</style>

Student.vue

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<template>
<div class="demo">
<h2 class="title">学校名称: {{ name }}</h2>
<h2 class="qwe">学校地址: {{ address }}</h2>
</div>
</template>

<script>
export default {
name: "School",
data() {
return {
name: "尚硅谷atguigu",
address: "北京",
};
},
};
</script>

<style lang="less" scoped>
.demo {
background-color: lightpink;
.qwe {
font-size: 50px;
}
}
</style>

App.vue

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<template>
 
<div>
   
<h2 class="title">标题</h2>
    <School />    
<hr />
    <Student />  
</div>
</template>

<script>
import Student from "./components/Student.vue";
import School from "./components/School.vue";

export default {
name: "App",
components: {
Student,
School,
},
};
</script>

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

<style></style>

main.js

1
2
3
4
5
6
7
8
9
import Vue from "vue";
import App from "./App.vue";

Vue.config.productionTip = false;

new Vue({
el: "#app",
render: (h) => h(App),
});

在组件中的 style 标签中定义了 scoped, 会在使用的 class 类上加上随机的 id, 在选择器中配合 id 来选择, 用来解决 css 选择器重名的问题

但是在 App.vue 组件中, 一般不用这个, 主要是 App 组件中写了样式, 就说明是很多组件都在使用的, 就不需要用 scoped 的

Module not found: Error: Can’t resolve ‘less-loader’ in ‘E:\Code\Vue\vue_test’