VUE
VUE常用命令和入门案例
vue的引入
通过cdn镜像引入
<script src="https://unpkg.com/vue/dist/vue.js"></script>
常用命令(重点)
1:v-on:事件(等同于@)
可以用 v-on 指令监听 DOM 事件,并在触发时运行一些 JavaScript 代码
2:v-text与v-html:文本
3:v-bind:属性
4:v-model:绑定表单(用于回显)
5:v-for:循环数据
for循环中key的使用
6:v-if与v-show:判断
VUE第一个代码解析
vue中写的代码要求都是json数据格式,只不过value的key可以省略双引号
<div id="app">
{{ message }} {{name}}
</div>
<script>
var app = new Vue({
el: '#app',
data: {
message: 'Hello Vue!'
name: "vue"
}
})
</script>
-
声明一个容器div装vue代码
-
用两个大括号声明了一个变量message
- 用来文本插值
-
new Vue 构造函数 生成一个vue对象
-
需要传递一个配置对象作为参数 配置对象是一个大括号
-
这个对象有两个重要的属性
-
el element元素
-
值一般是css选择器字符串
-
data 保存数据
-
使用对象存储数据
-
一般也会多层嵌套
data:{ name:'叶生', school:{ name:'学校名字', url:'学校地址' } } 直接调用name是名字 调用school.name是学校名字
-
-
-
-
页面使用两个大括号作为插值语法
- {{}}
-
容器里的代码被称为vue模板
-
容器和vue对象是一对一的关系
- 一个页面通常只有一个容器和一个vue对象,配合组件去使用
-
插值大括号里面可以放js表达式
- 比如1+1 new Date() 三元运算
- 表达式的概念
- a a+b fun(1) 三元运算
- 都可以用一个变量接受值
-
v-bind 把字符串对应的data的key绑定给等号左边的属性
- 可以动态的帮标签属性绑定值
- 简写是冒号 :
指令语法和插值语法
- 指令语法
- 用于解析标签 包括,标签属性,标签内容,绑定事件
- 比如v-bind:href="xxx" 可以简写为 :href="xxx" xxx同样是js表达式
- 插值语法
- 用于解析标签体内容
- {{xxx}} xxx是表达式,且可以直接读取到data的所有属性
数据绑定
- 单项绑定
- vue对象的改变可以修改容器对象
- 但是容器对象的改变不可以修改vue对象
- v-bind就是单项绑定
- 双向绑定
- 可以互相影响
- v-model是双向绑定
- v-model只能应用在表单类元素(输入类元素),必须有value值
- v-model默认收集的就是value值
- input 单选框 多选框 select框 等
- 可以简写为v-model 不需要:value 因为默认就是value
<input type="text" v-model="name">
el和data 的两种写法
<script type="text/javascript">
//阻止vue在启动时生成生成提示
Vue.config.productionTip = false;
//创建vue实例
//参数是大括号,配置对象
let vm = new Vue({
//data中用于存储数据,数据供el指定的容器去使用
el: '#app',
//data第一种写法,对象式
// data: {
// name:'xxxx'
// },
//data第二种写法,函数式,以后学到组件的时候,就用这个
// data:function(){
//简写版
data(){
//这个函数必须返回对象
return{
name:'xxx'
}
}
})
//两种都可以,这个比较灵活
// vm.$mount('#app')
</script>
- 方法名可以省略function关键字
不使用return包裹的数据会在项目的全局可见,会造成变量污染;使用return包裹后数据中变量只在当前组件中生效,不会影响其他组件
MVVM模型
- M 模型(model) 对应data中的数据 数据就是一个对象
- V 视图(View) 模板
- VM 视图模型(ViewModel) vue实例对象
视图html界面并不直接操作数据,而是通过vm间接存取数据
模型层也是通过vm间接存取数据,所以是双向改变
Object.definedproperty方法
-
定义(添加)对象属性方法
-
传三个参数
-
1.给哪个对象添加
-
2.添加的属性名
-
3.给一个配置对象
<script> //创建一个person对象,给他添加年龄属性 let person = { name:'张三', gender:'男', } //使用对象定义方法 //需要传三个参数,给哪个对象添加参数,属性名,配置对象(属性值) Object.defineProperty(person,'age',{ value:18, //使其可以便利 enumerable:true, //控制属性是否可以被修改 writeable:true, //属性是否可以被删除 configurable:true, }) console.log(person); </script>
-
使用定义对象属性方法,添加的属性是不能被枚举的
- 也就是说不能被遍历
-
-
Object.keys(对象名) 提取所有的属性名作为一个数组
循环遍历
for in 便历出来的是属性值 需要取出索引,需要加一个参数
- 如果直接写一个变量,默认就是值,如果写三个变量:依次代表----值 键 索引
<p v-for="(p,index) in person">{{p}} {{index}}</p>
- for of 遍历的是value
<!-- 1、简单的列表渲染 -->
<ul>
<li v-for="n in 10">{{ n }} </li>
</ul>
如果想获取索引,则使用index关键字(名字无所谓,i也可以,位置在最后面即可)
圆括号中的index必须放在后面
<li v-for="(n, index) in 5">{{ n }} - {{ index }} </li>
遍历数据列表和对象区别
值 键 索引 都统一
对象 值,键
列表 值,索引
vue事件
-
默认不传参有一个event形参,代表元素对象,
-
传参之后,就没了,可以在传参时,用$event占位
-
事件修饰符
- 可以在标签事件后面加上
- prevent 阻止默认事件
- stop 阻止冒泡
- once 事件只触发一次
- 以上三个 都是常用 @click.prevent = “事件名”
- 可以连着写 @click.stop.prevent = “事件名”
-
键盘事件
-
按键别名
-
keyup.enter 键盘回车之后才获取元素-----常用
-
delete 删除或者退格键-----常用
-
esc 退出-----常用
-
space 空格-----常用
-
up
-
down
-
left
-
right
-
必须和keydown使用
- tab 换行-----常用
- ctrl
- alt
- shift
- meta----------widows键
-
其他的可以使用key 值,event.key参数可以获得按键名字
-
多单词的key名,使用全小写,单词间用-隔开
计算属性
必须使用已有的属性计算,计算出来的属性会在vm中可以使用this调用
底层使用了对象定义方法
-
computed:{ key: {配置对象}}
computed:{ 属性名: { //和使用对象定义方法一样 //初次读取的时候调用,然后会做缓存 //依赖的数据发生变化时 get(){ 调用属性返回 } //计算属性很少使用set set(){ 设置属性返回 } }} //精简写法,只用get computed:{ 属性名(){调用属性返回} } 调用的时候不能添加小括号!!! {{fullname}}
监视属性
可以监视属性的变化
当属性变化时,函数自动调用,监视的属性必须存在
watch:{ 监听的data中的数据属性名:function(参数){ } } 参数:就是监听的数据属性值,名字叫啥都可以 完整的写法 watch:{ 属性名:{ 有个配置对象 //当属性发生改变时调用 handler(newValue,oldValue ){ 可以有两个参数,新的值和旧的值 } } } ;简写 watch:{ 监听的data中的数据属性名(参数){可以有两个参数,新的值和旧的值 } }
-
-
关于vue的函数
被vue管理的函数写成普通函数,this指向的才是vm
不被vue管理的函数(定时器的回调函数,ajax的回调函数,promise等),写出箭头函数
这样箭头函数没有自己的this,才会往外找,否则是window对象
Mode
vue的小测试
属性绑定
<style>
.red{
color: red;
}
.big{
font-size: 30px;
}
<div id="app">
<p :class="{red:isRed,big:isBig}">大括号测试动态绑定类</p>
<p :class="[ok ? 'red' : '']">中括号可以使用三元运算</p>
<p :class="[showRed,'big']">直接显示类</p>
<a :href="url">动态连接</a>
</div>
<script type="text/javascript">
//阻止vue在启动时生成生成提示
Vue.config.productionTip = false;
let vm = new Vue({
el: '#app',
data: {
//true表示引用这个类
isRed:true,
isBig:true,
ok:true,
//值是类名
showRed:'red',
url:'http://www.baidu.com'
},
})
</script>
计数器
每点击一次加一
<div id="app">
<div>一个点击了{{clickNumber}}次</div>
<button type="button" @click="count">点击</button>
</div>
<script type="text/javascript">
let vm = new Vue({
el:'#app',
data:{
clickNumber:0
},
methods:{
count:function(){
this.clickNumber++;
}
}
})
</script>
vue表格练习
动态添加数据和删除,未校验
<div id="app">
<table>
<thead>
<tr>
<th>编号</th>
<th>姓名</th>
<th>年龄</th>
<th>专业</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<!--
循环遍历属性值和下标,下标是为了删除当前元素
-->
<tr v-for="(p,index) in person">
<td>{{p.id}}</td>
<td>{{p.name}}</td>
<td>{{p.age}}</td>
<td>{{p.subject}}</td>
<td>
<input type="button" value="delet" @click="drop(index)">
</td>
</tr>
</tbody>
</table>
<form action="#" method="get">
编号: <input type="text" v-model="per.id"><br>
姓名: <input type="text" v-model="per.name"><br>
年龄: <input type="text" v-model="per.age"><br>
专业: <input type="text" v-model="per.subject"><br>
<input type="submit" value="添加数据" @click="insert()"/>
</form>
</div>
<script type="text/javascript">
let vm = new Vue({
el:'#app',
data:{
person:[
{
id:1,
name:"叶子",
age:16,
subject:"java"
},
{
id:2,
name:"叶一",
age:13,
subject:"php"
},
{
id:3,
name:"叶天",
age:26,
subject:"JavaScript"
},
],
per:{
id:"",
name:"",
age:"",
subject:""
},
},
methods:{
//删除元素
drop(index){
//splice,第一个参数是删除的下标,第二个参数是删除几个
this.person.splice(index,1);
},
//添加元素
insert(){
if(this.per.id==""){
alert("添加失败");
}else{
//添加到数组后面
this.person.push(this.per);
//由于是双向绑定,不清空的话,输入框影响表格内容
this.per = {};
}
}
}
})
</script>
跑马灯
让文字自动移动
<div id="app">
<h4>{{ name }}</h4>
<input type="button" value="浪起来" @click="lang()" />
<input type="button" value="低调" @click="stop()" />
</div>
<script type="text/javascript">
let vm = new Vue({
el: '#app',
data: {
//文字
name:'不要在浪啦!!!',
//定时器
intervalId:null,
},
methods:{
//让文字自动走
lang(){
//避免重复开启定时器
if(this.intervalId != null){
return;
}
//设置定时器
this.intervalId = setInterval(() => {
//先获得第一个字
let start = this.name.substring(0,1);
//后面的文字
let end = this.name.substring(1);
//拼接文字
this.name = end + start;
//每隔400毫秒走一下
},400)
},
//文字停止走动
stop(){
//清除定时器
clearInterval(this.intervalId);
//重置为空
this.intervalId = null;
}
}
})
</script>
切换选项卡
<style>
/* 主体样式 */
.tab_con {
width: 500px;
height: 350px;
margin: 50px auto 0;
}
/* 选项卡高度 */
.tab_btns {
height: 50px;
}
/* 选项卡样式 */
.tab_btns input {
width: 100px;
height: 50px;
background: #ddd;
border: 0px;
outline: none;
}
/* 选中样式 */
.tab_btns .active {
background: pink;
}
/* 内容页高度 */
.tab_cons {
height: 300px;
background: gold;
}
/* 内容页样式,默认为不显示 */
.tab_cons div {
height: 300px;
line-height: 300px;
text-align: center;
display: none;
font-size: 30px;
}
/* 当前样式默认显示 */
.tab_cons .current {
display: block;
}
</style>
<div class="tab_con" id="app">
<div class="tab_btns">
<input type="button" value="按钮一" :class="num==0 ? 'active' : '' " @click="num = 0">
<input type="button" value="按钮二" :class="num==1 ? 'active' : '' " @click="num = 1">
<input type="button" value="按钮三" :class="num==2 ? 'active' : '' " @click="num = 2">
</div>
<div class="tab_cons">
<div :class="num == 0 ? 'current' : '' ">第一个页面</div>
<div :class="num == 1 ? 'current' : '' ">第二个页面</div>
<div :class="num == 2 ? 'current' : '' ">第三个页面</div>
</div>
</div>
<script type="text/javascript">
//阻止vue在启动时生成生成提示
Vue.config.productionTip = false;
let vm = new Vue({
el: '#app',
data: {
//默认是第一个选项卡
num:0
},
})
</script>
for的key使用----
如果 v-for 有问题,必须 在使用 v-for 的同时,指定 唯一的 字符串/数字 类型 :key 值
列表数据修改的时候,他会根据key值去判断某个值是否修改,如果修改,则重新渲染这一项,否则复用之前的元素;
<div id="app">
<div>
<label>Id:
<input type="text" v-model="id">
</label>
<label>Name:
<input type="text" v-model="name">
</label>
<input type="button" value="添加" @click="add">
</div>
<!-- 注意: v-for 循环的时候,key 属性只能使用 number获取string -->
<!-- 注意: key 在使用的时候,必须使用 v-bind 属性绑定的形式,指定 key 的值 -->
<!-- 在组件中,使用v-for循环的时候,或者在一些特殊情况中,如果 v-for 有问题,必须 在使用 v-for 的同时,指定 唯一的 字符串/数字 类型 :key 值 -->
<p v-for="item in list" :key="item.id">
<input type="checkbox">{{item.id}} --- {{item.name}}
</p>
</div>
<script>
// 创建 Vue 实例,得到 ViewModel
var vm = new Vue({
el: '#app',
data: {
id: '',
name: '',
list: [
{ id: 1, name: '李斯' },
{ id: 2, name: '嬴政' },
{ id: 3, name: '赵高' },
{ id: 4, name: '韩非' },
{ id: 5, name: '荀子' }
]
},
methods: {
add() { // 添加方法
//unshift() 方法可向数组的开头添加一个或更多元素,并返回新的长度。
this.list.unshift({ id: this.id, name: this.name })
}
}
});
</script>
v-if与v-show
v-if是根据表达式的值来决定是否渲染元素,整行在或者消失
v-show是根据表达式的值来切换元素的display css属性,none或者block
v-if修改了dom对象(适合不经常修改),v-show只修改了样式(适合频繁切换)
<div id="app">
<p v-if="ok">这是使用了v-if的p标签</p>
<p v-else>这是使用了v-else的p标签</p>
<p v-show="ok">这是使用v-show的p标签</p>
<div v-if="code=='A'">A</div>
<div v-else-if="code=='B'">B</div>
<div v-else-if="code=='C'">C</div>
<div v-else>NOT A/B/C</div>
</div>
</body>
<script type="text/javascript">
var vm = new Vue({
el: "#app",
data: {
ok: true,
code: 'D'
}
})
</script>
数组 splice() 方法
可以删除或者添加元素
index | 必需。整数,规定添加/删除项目的位置,使用负数可从数组结尾处规定位置。 |
---|---|
howmany | 必需。要删除的项目数量。如果设置为 0,则不会删除项目。 |
item1, …, itemX | 可选。向数组添加的新项目。 |
文本对话框
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<style type="text/css">
.talk_con {
width: 600px;
height: 500px;
border: 1px solid #666;
margin: 50px auto 0;
background: #f9f9f9;
}
.talk_show {
width: 580px;
height: 420px;
border: 1px solid #666;
background: #fff;
margin: 10px auto 0;
overflow: auto;
}
.talk_input {
width: 580px;
margin: 10px auto 0;
}
.whotalk {
width: 80px;
height: 30px;
float: left;
outline: none;
}
.talk_word {
width: 420px;
height: 26px;
padding: 0px;
float: left;
margin-left: 10px;
outline: none;
text-indent: 10px;
}
.talk_sub {
width: 56px;
height: 30px;
float: left;
margin-left: 10px;
}
.atalk {
margin: 10px;
}
.atalk span {
display: inline-block;
background: #0181cc;
border-radius: 10px;
color: #fff;
padding: 5px 10px;
}
.btalk {
margin: 10px;
text-align: right;
}
.btalk span {
display: inline-block;
background: #ef8201;
border-radius: 10px;
color: #fff;
padding: 5px 10px;
}
</style>
<script src="js/v2.6.10/vue.js"></script>
<script type="text/javascript">
// 写出对应功能代码
window.onload = function() {
var vm = new Vue({
el: "#app",
data: {
//内容集合,who表示谁,say表示对话内容
content: [{
who: 'A',
say: '吃饭了吗'
},
{
who: 'B',
say: '吃饭了吗'
},
],
txt: '', //对话框内容
sel: '0' //a还是b
},
methods: {
fnAdd: function() {
if (this.txt == '') {
alert('请您输入内容')
return
}
this.content.push({
who: this.sel == '0' ? 'A' : 'B',//0默认是A
say: this.txt //文本内容
})
this.txt = ''
oTxt.focus()//文本框获得焦点
//文本框往下走,等待指定时间后执行函数
setTimeout(function() {//固定方法
//scrollLeft滚动条的垂直偏移:数字随意
document.getElementById("words").scrollTop = '9999'
}, 1)//一毫米后调用该函数
}
}
})
//获得文本框
var oTxt = document.getElementById("talkwords")
//文本框获得焦点
oTxt.focus()
}
</script>
</head>
<body>
<div class="talk_con" id="app">
<div class="talk_show" id="words">
<div :class="[item.who=='A'? 'atalk':'btalk']" v-for="item in content">
<span>{{item.who}}说:{{item.say}}</span>
</div>
<!--<div class="btalk"><span>B说:还没呢,你呢?</span></div>-->
</div>
<div class="talk_input">
<select class="whotalk" id="who" v-model="sel">
<option value="0">A说:</option>
<option value="1">B说:</option>
</select>
<input type="text" class="talk_word" id="talkwords" v-model="txt">
<input type="button" value="发送" class="talk_sub" id="talksub" @click="fnAdd">
</div>
</div>
</body>
</html>
VueJS生命周期
钩子函数: mounted 常用
- beforeCreate vue创建之前
- created vue创建之后,页面初始化之前
- beforeMount 挂载dom之前 页面未创建完成
- mounted 挂载dom之后 页面创建完成
- beforeUpdate 数据更新之前
- updated 数据更新之后
- beforeDestroy vue 销毁之前
- destroyed vue销毁之后
ajax请求
引入axios
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
//通过给定的ID来发送请求
axios.get('/user?ID=12345')
.then(function(response){
console.log(response);
})
.catch(function(err){
console.log(err);
})
.finally(function(){
});
post请求
axios.post('/user',{
name:'张三',
age:'22'
}).then(function(res){
console.log(res);
}).catch(function(err){
console.log(err);
})
.finally(function(){
});
组件(重点)
局部组件
components局部组件,key是组件名和组件值
组件的名字,自定义
template 组件模板,固定单词
<div id="app">
//组件的名字,自定义
<componentName></componentName>
</div>
<script>
let vm = new Vue({
el: '#app',
// 定义局部组件,这里可以定义多个局部组件
components: {
//组件的名字,自定义
'componentName': {
//组件的内容
template: '这里放自定义的标签'
},
'可以放多个': {
template: '这里放自定义的标签'
}
}
})
</script>
全局组件
有的组件会在不同页面使用,这个时候就可以考虑用全局组件
将局部组件抽离出来,使用Vue. 抽离
创建自定义js,放置全局组件
// 定义全局组件,其实就是局部组件抽离
//组件的名字,自定义
Vue.component('componentName', {
//组件的内容
template: '这里放自定义的标签'
})
使用的地方,引入自定义js即可
路由
允许我们通过不同的 URL 访问不同的内容
需要载入 vue-router 库
<script src="https://cdn.staticfile.org/vue/2.4.2/vue.min.js"></script>
<script src="https://cdn.staticfile.org/vue-router/2.7.0/vue-router.min.js"></script>
主体
<div id="app">
<h1>Hello App!</h1>
<p>
<!--
router-link 相当于就是超链
to 相当于就是 href
-->
<!-- 使用 router-link 组件来导航. -->
<!-- 通过传入 `to` 属性指定链接. -->
<!-- <router-link> 默认会被渲染成一个 `<a>` 标签 -->
<router-link to="/">首页</router-link>
<router-link to="/student">会员管理</router-link>
<router-link to="/teacher">讲师管理</router-link>
<router-link to="/member">成员管理</router-link>
</p>
<!-- 路由出口 -->
<!-- 路由匹配到的组件将渲染在这里 -->
<!-- 点击上面的连接, 对应的内容就会显示在router-view 这里 -->
<router-view></router-view>
</div>
vue
<script>
// 申明模板( html 片段 )
// 1. 定义(路由)组件。
// 可以从其他文件 import 进来
const Welcome = { template: '<div>欢迎</div>' }
const Student = { template: '<div>student list</div>' }
const Teacher = { template: '<div>teacher list</div>' }
const member = {template: '<div> member list</div>'}
// 2. 定义路由
// 每个路由应该映射一个组件。
//redirect表示默认渲染,没有这个就是空白
const routes = [
{ path: '/', redirect: '/welcome' }, //设置默认指向的路径
{ path: '/welcome', component: Welcome },
{ path: '/student', component: Student },
{ path: '/teacher', component: Teacher },
{ path: '/member',component: member}
]
// 3. 创建 router 实例,然后传 `routes` 配置
const router = new VueRouter({
routes // (缩写)相当于 routes: routes
})
//给vue对象绑定路由
// 4. 创建和挂载根实例。
// 从而让整个应用都有路由功能
const app = new Vue({
el: '#app',
router
})
// 现在,应用已经启动了!
</script>
以上使用了同名省略
vue-cli
vue脚手架,组件式地开发。
安装
npm install -g @vue/cli
原型工具
npm install -g @vue/cli-service-global
入门案例
新建组件 student.vue
<template>
<div >
<h2>学生名称: {{name}}</h2>
<h2>学生年龄: {{age}}</h2>
</div>
</template>
<script>
//暴露组件,默认暴露
export default {
name:'student',
data(){
return{
name:'叶生',
age:18
}
}
}
</script>
学校组件school.vue
<template>
<div class="demo">
<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>
.demo{
background-color: pink;
}
</style>
全局组件App.vue
<template>
<div>
<img src="./assets/logo.png">
<school></school>
<student></student>
<input type="text">
<button>原生按钮</button>
<el-row>
<el-button round>圆角按钮</el-button>
<el-button type="primary" round>主要按钮</el-button>
<el-button type="success" round>成功按钮</el-button>
<el-button type="info" round>信息按钮</el-button>
<el-button type="warning" round>警告按钮</el-button>
<el-button type="danger" round>危险按钮</el-button>
</el-row>
</div>
</template>
<script>
//引入组件,直接使用函数名即可
import school from './components/school'
import student from './components/student'
//默认导出方式
export default {
name:'App',
components:{ //注册主键
school, //同名省略
student
}
}
</script>
入口文件 main.js
// 项目入口文件
//引入vue,脚手架引入npm i vue
import Vue from 'vue'
//引入全局组件
import App from './App.vue'
// 引入饿了么
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
//关闭vue生产提示
Vue.config.productionTip = false
//应用
Vue.use(ElementUI);
//创建vue实例
new Vue({
//将app组件放入容器中
render: h => h(App),
/*
//这里的render: h=> h(App)是es6的写法
//暂且可理解为是渲染App组件
*/
}).$mount('#app') //容器id叫app
/*
手动挂载到id为app的dom中的意思
当Vue实例没有el属性时,则该实例尚没有挂载到某个dom中;
假如需要延迟挂载,可以在之后手动调用vm.$mount()方法来挂载
*/
主页文件在public中
<!DOCTYPE html>
<html lang="">
<head>
<meta charset="utf-8">
<!-- 针对ie浏览器的配置 -->
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<!-- 开启移动端的理想视口 -->
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<!-- <%= BASE_URL %>表示当前目录./ -->
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<!-- 配置网页标题 -->
<title><%= htmlWebpackPlugin.options.title %></title>
</head>
<body>
<!-- 如果浏览器不支持js会渲染下面的信息 -->
<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>
通过 vue-cli 创建一个项目
创建命令
vue create hello-world
替换文件
组件放在components目录下
运行项目
npm run serve