四、脚手架
4.1 初始化
- 骨架
# 配置镜像
npm config set registry https://registry.npm.taobao.org
# 安装
npm install -g @vue/cli
# 创建项目
vue create vue_test
# 运行项目
cd vue_test
npm run serve
# 访问项目
http://localhost:8080/
- 脚手架文件结构
main.js -> App.vue -> School.vue + Student.vue -> 渲染完毕后装载到 index.html
public 文件夹:一般放置一些静态资源(图片),需要注意,放在这里的静态资源 webpack 进行打包的时候,会原封不动 打包到 dist 文件夹 中;
assets 文件夹:一般也是放置静态资源(一般放置多个组件共用的静态资源),需要注意,放置在 assets 文件夹里面的静态资源再 webpack 打包的时候,会把这些静态资源当作一个模块,打包到 JS 文件 里面。
<!-- App.vue -->
<template>
<div>
<img src="./assets/logo.png" alt="logo">
<School></School>
<Student></Student>
</div>
</template>
<script>
//引入组件
import School from './components/School'
import Student from './components/Student'
export default {
name:'App',
components:{
School,
Student
}
}
</script>
<!-- index.html -->
<!DOCTYPE html>
<html lang="">
<head>
<meta charset="utf-8">
<!-- 针对IE浏览器的一个特殊配置,含义是让IE浏览器以最高的渲染级别渲染页面 -->
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<!-- 开启移动端的理想视口 -->
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<!-- 配置页签的图标,其中 <%= BASE_URL %> 部署时会被替换成public目录路径 -->
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<!-- 配置网页标题,其中 <%= htmlWebpackPlugin.options.title %> 部署时会被替换成package.json中的name -->
<title><%= htmlWebpackPlugin.options.title %></title>
</head>
<body>
<!-- 当浏览器不支持js时noscript中的元素就会被渲染 -->
<noscript>
<strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
</noscript>
<!-- 容器 -->
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
</html>
4.2 render 函数
/*
该文件是整个项目的入口文件
*/
//引入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函数去指定具体内容。
*/
//创建Vue实例对象---vm
new Vue({
el:'#app',
//render函数完成了这个功能:将App组件放入容器中
render: h => h(App)
})
4.3 ref 属性
1. 被用来给元素或子组件注册引用信息(id的替代者)
2. 应用在html标签上获取的是真实DOM元素,应用在组件标签上是组件实例对象(vc)
3. 使用方式:
1. 打标识:<h1 ref="xxx">.....</h1> 或 <School ref="xxx"></School>
2. 获取:this.$refs.xxx
<!-- App.vue -->
<template>
<div>
<h1 v-text="msg" ref="title"></h1>
<button @click="showDOM">点我输出上方的 DOM 元素</button>
<School ref="sch" />
</div>
</template>
<script>
// 引入 School 组件
import School from './components/School'
export default {
name: 'App',
data() {
return {
msg: '欢迎学习 Vue!'
}
},
methods: {
showDOM() {
// App 对应的 VueComponent 实例对象
console.log(this)
// App 中的 ref 为 title 的 DOM 元素
console.log(this.$refs.title)
// App 中的 ref 为 sch 的 VueComponent 实例对象
console.log(this.$refs.sch)
}
},
components: {School}
}
</script>
4.4 props 配置
- 配置方式
- 第一种方式(只接收):props:[‘name’]
- 第二种方式(限制类型):props:{name:String}
- 第三种方式(限制类型、限制必要性、指定默认值):
props:{
name:{
type:String, //类型
required:true, //必要性
default:'老王' //默认值
}
}
props 是只读的,Vue底层会监测你对props的修改,如果进行了修改,就会发出警告,若业务需求确实需要修改,那么请复制props的内容到data中一份,然后去修改data中的数据。
- 代码实验
<!-- App.vue -->
<template>
<div>
<!-- age 传的值默认就是字符串,:age 将引号内表达式运算后执行的结果作为值传递 -->
<Student name="李四" sex="女" :age="19" />
</div>
</template>
<script>
import Student from './components/Student'
export default {
name: 'App',
components: {Student}
}
</script>
<!-- Student.vue -->
<template>
<div>
<h1>{{msg}}</h1>
<h2>学生姓名:{{name}}</h2>
<h2>学生性别:{{sex}}</h2>
<h2>学生年龄:{{myAge}}</h2>
<button @click="updateAge">尝试修改接收到的年龄</button>
</div>
</template>
<script>
export default {
name: 'Student',
data() {
return {
msg: '我是一个尚硅谷的学生',
myAge: this.age
}
},
// props: ['name', 'sex', 'age'] // 简单接收
// 接收的同时对数据进行类型限制
// props: {
// name: String,
// age: Number,
// sex: String
// }
props: {
name: {
type: String,
required: true // 该属性是必穿的
},
age: {
type: Number,
default: 99
},
sex: {
type: String,
required: true
}
},
methods: {
updateAge() {
this.myAge++
}
}
}
</script>
4.5 mixin 混入
功能:可以把多个组件共用的配置提取成一个混入对象
- 实例
点击姓名弹出展示框展示姓名。
//mixin.js
export const mixin = {
methods: {
showName() {
alert(this.name)
}
}
}
<!-- Student.vue -->
<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]
}
</script>
<!-- School.vue -->
<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>
4.6 plugins 插件
功能:用于增强Vue。
本质:包含install方法的一个对象,install的第一个参数是Vue,第二个以后的参数是插件使用者传递的数据。
- plugins.js 定义插件
// 定义插件,一定要有 install 方法
export default {
install(Vue) {
//全局过滤器
Vue.filter('mySlice',function(value){
return value.slice(0,4)
})
//定义全局指令
Vue.directive('fbind',{
//指令与元素成功绑定时(一上来)
bind(element,binding){
element.value = binding.value
},
//指令所在元素被插入页面时
inserted(element){
element.focus()
},
//指令所在的模板被重新解析时
update(element,binding){
element.value = binding.value
}
})
//定义混入
Vue.mixin({
data() {
return {
x: 100,
y: 200
}
}
})
//给Vue原型上添加一个方法
Vue.prototype.hello = ()=>{alert('你好啊')}
}
}
- main.js 引入并使用插件
import Vue from 'vue'
import App from './App.vue'
// 引入插件
import plugins from './plugins'
Vue.config.productionTip = false
// 使用插件
Vue.use(plugins)
new Vue ({
el: '#app',
render: h => h(App)
})
- School.vue Student.vue 验证插件
<template>
<div>
<!-- 1. 过滤器:取字符串的前四个字符 -->
<h2>学校姓名:{{name | mySlice}}</h2>
<h2>学校地址:{{address}}</h2>
<button @click="testHelloOnVue">点我测试一下 hello 方法</button>
</div>
</template>
<script>
export default {
name: 'School',
data() {
return {
name: '尚硅谷atguigu',
address: '北京.昌平'
}
},
methods: {
testHelloOnVue() {
// 4. 直接调用原型上的 hello 方法
this.hello()
}
},
}
</script>
<template>
<div>
<h2>学生姓名:{{name}}</h2>
<h2>学生性别:{{sex}}</h2>
<!-- 2. 自动获取焦点 -->
<input type="text" v-fbind:value="name">
</div>
</template>
<script>
export default {
name: 'Student',
data() {
return {
name: '李四',
sex: '女'
}
}
}
</script>
4.7 scoped 样式生效范围
作用:让样式在局部生效,防止冲突。
<template>
<div class="demo">
<h2>学校姓名:{{name}}</h2>
<h2>学校地址:{{address}}</h2>
</div>
</template>
<script>
export default {
name: 'School',
data() {
return {
name: '尚硅谷atguigu',
address: '北京.昌平'
}
}
}
</script>
<style scoped>
.demo {
background-color: aqua;
}
</style>
<template>
<div class="demo">
<h2>学生姓名:{{name}}</h2>
<h2>学生性别:{{sex}}</h2>
</div>
</template>
<script>
export default {
name: 'Student',
data() {
return {
name: '李四',
sex: '女'
}
}
}
</script>
<style scoped>
.demo {
background-color: burlywood;
}
</style>