vue引入
下载源码
cdn引入(Content Delivery Network,即内容分发网络)
hello vue
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js">script>
head>
<body>
<div class="app">
<p>{
{msg}}p>
div>
<script>
/**
* 创建view实例
* 导入vue包后,在浏览器内存中就会多一个Vue的构造函数
* 下面new出来的vm对象就是MVVM中的VM调度者
*/
var vm=new Vue({
el: '.app',//vue实例控制页面的哪个区域
data: {
//存放el要用到的数据
msg:'hello,vue!'//通过vue提供的指令,很方便的把数据渲染到页面上,程序员不用动手操作DOM元素
}
})
script>
body>
html>
<body>
<div id="app">
<p>{
{msg}}p>
<input type="text" v-model="msg">
div>
<script>
var vm=new Vue({
el:'#app',
data:{
msg:'学习vue'
}
})
script>
body>
解决{ {对象}}闪现的问题
<div id="app">
<p>{
{msg}}p>
<p v-text="msg">p>
div>
<script>
var vm=new Vue({
el:'#app',
data:{
msg:'学习vue'
}
})
script>
<div id="app">
<p>{
{msg}}p>
<p v-html="msg">p>
div>
<script>
var vm=new Vue({
el:'#app',
data:{
msg:'学习vue
'
}
})
script>
和css规则[v-cloak]{display:none}一起使用,可以隐藏未编译的Mustache直到实例准备完毕
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js">script>
<style>
[v-cloak]{
display: none;
}
style>
head>
<body>
<div id="app">
<p v-cloak>{
{msg}}p>
div>
<script>
var vm=new Vue({
el:'#app',
data:{
msg:'学习vue'
}
})
script>
body>
html>
<body>
<div id="app">
<p v-for="item in 10">第{
{item}}轮循环p>
div>
<script type="text/javascript">
var vm = new Vue({
el: '#app',
data: {
list: [1, 2, 3, 4, 5, 6, 7],
listC:[
{
id:1,name:'张三'},
{
id:2,name:'李四'},
{
id:3,name:'王五'},
{
id:4,name:'陈六'}
],
userInfo:{
id:1,
name:'张三',
gender:'男'
}
}
})
script>
body>
注意 在2.2.0+版本中,当使用v-for时,key必须使用
Vue.js中v-for在更新已经渲染过的元素列表时,默认使用“就地复用”策略。为了方便vue能跟踪每个结点的身份,从而重用和重新排序现有元素,我们需要给一个唯一的key属性(key的值必须为string或number类型)
<body>
<div id="app">
<div>
<lable>Id:
<input type="text" v-model="id">
lable>
<lable>Name:
<input type="text" v-model="name">
lable>
<input type="button" value="添加" @click="add">
div>
<div>
<p v-for="item in list" :key="item.id">
<input type="checkbox"> {
{item.id}} {
{item.name}}
p>
div>
div>
<script type="text/javascript">
var vm = new Vue({
el: '#app',
data: {
id:'',
name:'',
list: [
{
id: 1, name: '张三'},
{
id: 2, name: '李四'},
{
id: 3, name: '王五'},
{
id: 4, name: '陈六'}
]
},
methods:{
add(){
/*unshift向数组中队头添加对象*/
this.list.unshift({
id:this.id,name:this.name});
}
}
})
script>
body>
div id="app">
<input type="button" value="toggle" @click="flag=!flag">
<h3 v-if="flag">这是v-if控制的元素h3>
<h3 v-show="flag">这是v-show控制的元素h3>
div>
<script type="text/javascript">
var vm = new Vue({
el: '#app',
data: {
flag:true
}
})
script>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js">script>
<style>
.red{
color: red;
}
.italic{
font-style: italic;
}
.active{
letter-spacing: 0.5em;
}
style>
head>
<body>
<script type="text/javascript">
var vm=new Vue({
el: '#h1',
data:{
msg:'我是一级标题',
flag:false,
classObj:['red','italic','active']
}
})
script>
body>
html>
<body>
<h1 id="h1" :style="[styleObj,styleObj2]">{
{msg}}h1>
<script type="text/javascript">
var vm=new Vue({
el: '#h1',
data:{
msg:'我是一级标题',
styleObj:{
color:'red','font-size':'40px'},
styleObj2:{
fontStyle:'italic'}
}
})
script>
body>
<div id="app">
<p>{
{msg | filter1}}p>
div>
<script type="text/javascript">
/*
创建过滤器
filter1:为过滤器名称
msg:传递过来的数据,通过管道符左边的传递的数据
*/
Vue.filter('filter1',function (msg) {
return msg.replace(/你/g,'他们');
})
var vm = new Vue({
el: '#app',
data: {
msg:'你好,你吃过了吗,你要去哪?'
}
})
script>
<div id="app">
<p>{
{msg | filter1('他们','111')}}p>
div>
<script type="text/javascript">
//创建过滤器
Vue.filter('filter1',function (msg,arg,arg2) {
return msg.replace(/你/g,arg+arg2);
})
var vm = new Vue({
el: '#app',
data: {
msg:'你好,你吃过了吗,你要去哪?'
}
})
script>
<p>{
{msg | filter1 |filter2 }}p>
上面定义的是全局过滤器,下面定义私有过滤器
在new Vue({})中添加filters
filters: {
//私有过滤器
dateFormat:function (dateStr,pattern='') {
//根据给定的时间字符串,得到特定的时间
var dt=new Date(dateStr);
//提取年月日
var y=dt.getFullYear();
var m=dt.getMonth()+1;//月份从0开始
var d=dt.getDate();
if(pattern.toLocaleLowerCase()=='yyyy-mm-dd'){
return `${
y}-${
m}-${
d}`;
}else{
//最全时间格式
var hh=dt.getHours();
var mm=dt.getMinutes();
var ss=dt.getSeconds();
return `${
y}-${
m}-${
d} ${
hh}:${
mm}:${
ss}~~~~`;
}
}
}
当全局和私有过滤器同名且同时存在,就近原则,优先调用私有过滤器
数组名.some((str)=>{
return str==='xxx'
//如果有就是true否则为false
})
this.list.some((item,i)=>{
if(item.id==id){
//删除下标从i开始,删除1个
this.list.splice(i,1);
return true;
}
})
vue中提供的按键修饰符
https://cn.vuejs.org/v2/guide/events.html
在js中每个按键都对应具体的数字,可以直接使用,也可以自定义修饰符
<input type="text" class="form-control" v-model="name" @keyup.113="add">
<input type="text" class="form-control" v-model="name" @keyup.f2="add">
<script>
Vue.config.keyCodes.f2=113;
script>
https://cn.vuejs.org/v2/guide/custom-directive.html
<input type="text" class="form-control" v-model="keywords" v-focus v-color>
//自定义指令名称为focus 使用时v-focus
Vue.directive('focus',{
//el参数,是一个原生的JS对象
inserted:function (el) {
//在插入DOM时会执行一次
el.focus()
//Js行为相关的都在inserted中设置
}
})
Vue.directive('color',{
//指令绑定元素时操作,只会触发一次
bind:function(el){
//和样式相关的操作都在bind中操作
el.style.color='red';
}
})
传递颜色值
<input type="text" class="form-control" v-model="keywords" v-color="'blue'">
Vue.directive('color',{
//指令绑定元素时操作,只会触发一次
bind:function(el,binding){
//和样式相关的操作都在bind中操作
el.style.color=binding.value;
}
})
https://github.com/pagekit/vue-resource/blob/develop/docs/http.md
methods:{
getInfo(){
this.$http.get('http://10.3.242.250:3000/').then(response => {
console.log(response.body);
});
},
postInfo(){
this.$http.post('http://10.3.242.250:3000/list',{
},{
emulateJSON:true})
.then(result=>{
console.log(result.body)
})
},
jsonpInfo(){
this.$http.jsonp('ip地址').then(result=>{
console.log(result.body)
})
}
}
什么是组件:
组件的出现 ,就是为了拆分Vue实例的代码量的,能够让我们以不同的组件,来划分不同的功能模块,将来我们需要什么样的功能,就可以去调用对应的组件即可;
组件化和模块化的不同:
<div id="app">
<mycom1>mycom1>
div>
<script type="text/javascript">
//使用Vue.extend来创建全局Vue组件
var com1=Vue.extend({
//通过template属性指定组件要展示的HTML结构
template:'只是使用Vue.extend创建的组件
'
})
//使用Vue.component('组件名称',创建出来的组件模板对象)
/**
*Vue.component定义全局变量时,组件使用驼峰命名,则在引用组件的时候需要把大写的驼峰改成小写的字母,
* 同时,两个单词之间使用'-'链接
*
*如果不适用驼峰,则直接拿名称来使用
*/
/*Vue.component('myCom1',com1);*/
/*Vue.component('mycom1',com1);*/
/*两步合成一步*/
Vue.component('mycom1',Vue.extend({
//通过template属性指定组件要展示的HTML结构
template:'只是使用Vue.extend创建的组件
'
}));
var vm = new Vue({
el: '#app',
data: {
msg:'ok'
},
methods:{
show(){
console.log('执行了show方法')
}
}
})
script>
body>
/*两步合成一步*/
Vue.component('mycom2',{
//通过template属性指定组件要展示的HTML结构
template:'只是使用Vue.extend创建的组件
'
});
无论时那种方式创建组件,template属性指向的模板内容,必须有且只能有唯一的一个根元素
3、template单独写
<div id="app">
<mycom3></mycom3>
</div>
<!--在被控制的#app外面,使用template元素,定义组件的html模板结构-->
<template id="tmpl">
<div>
<h2>只是使用Vue.extend创建的组件</h2>
</div>
</template>
<script type="text/javascript">
/*两步合成一步*/
Vue.component('mycom3',{
//通过template属性指定组件要展示的HTML结构
template:'#tmpl'
});
var vm = new Vue({
el: '#app',
data: {
}
})
</script>
<div id="app">
<mycom4></mycom4>
</div>
<!--在被控制的#app外面,使用template元素,定义组件的html模板结构-->
<template id="tmpl">
<div>
<h2>只是使用Vue.extend创建的组件</h2>
</div>
</template>
<script type="text/javascript">
var vm = new Vue({
el: '#app',
data: {
},
components:{
mycom4:{
template:'#tmpl'
}
}
})
</script>
<div id="app">
<input type="button" value="登录" @click="flag=true">
<input type="button" value="祖册" @click="flag=false">
<login v-if="flag">login>
<register v-else="flag">register>
div>
<script type="text/javascript">
/*两步合成一步*/
Vue.component('login',{
template:'登录组件
'
});
Vue.component('register',{
template:'注册组件
'
})
var vm = new Vue({
el: '#app',
data: {
flag:true
}
})
script>
<div id="app">
<input type="button" value="登录" @click="compName='login'">
<input type="button" value="注册" @click="compName='register'">
<component :is="compName">component>
div>
<script type="text/javascript">
/*两步合成一步*/
Vue.component('login',{
template:'登录组件
'
});
Vue.component('register',{
template:'注册组件
'
})
var vm = new Vue({
el: '#app',
data: {
compName:'login'
}
})
script>
<div id="app">
<com1 v-bind:parentmsg="msg">com1>
div>
<script type="text/javascript">
var vm = new Vue({
el: '#app',
data: {
msg:'这是父组件中的值'
},
/*定义子组件*/
components:{
//子组件无法默认访问到父组件中的data上的数据和methods中的方法
com1:{
//子组件中data数据是自身私有的,可以修改
data(){
return{
title:'123',
content:'qqq'
}
},
template:'这是子组件------{
{parentmsg}}
',
//props是一个数组类型,中的数据,都是父组件传递给子组件的,不可以修改
props:['parentmsg']
}
}
})
script>
<div id="app">
<com1 @func="show">com1>
div>
<template id="tmp1">
<div>
<h1>这是子组件h1>
<input type="button" value="这是子组件的按钮,点击它,触发父组件传递过来func方法" @click="myclick">
div>
template>
<script type="text/javascript">
//定义一个自变量类型的组件模板对象
var com1={
template: '#tmp1',//通过指定id,加载对应的template元素中的内容,当做组件的HTML结构
methods:{
myclick(){
//通过调用子组件自身的$emit方法,传递自定义的事件名,如果方法有参数,对应传递参数
this.$emit('func','123')
}
}
}
var vm = new Vue({
el: '#app',
data: {
msg:'这是父组件中的值'
},
/*定义子组件*/
components:{
com1
},
methods:{
show:function (data) {
console.log('这是父组件show方法'+data)
}
}
})
script>
通过子组件调用父组件的事件,也可以把子组件的数据传递给父组件
单独事件中心管理组件间的通信
var eventHub=new Vue()
监听事件与销毁事件
eventHub. o n ( 函 数 名 , 函 数 体 ) e v e n t H u b . on(函数名,函数体) eventHub. on(函数名,函数体)eventHub.off(函数名)
触发事件
eventHub.$emit(函数名,参数)
<div id="app">
<div>
<span>父组件span>
<button @click='handle'>销毁事件button>
div>
<test-tom>test-tom>
<test-jerry>test-jerry>
div>
<script>
//事件中心
var eventHub=new Vue();
//组件test-tom
Vue.component("test-tom", {
data() {
return {
num: 0
}
},
template: `
TOM:{
{num}}
`,
methods: {
handle:function(val){
eventHub.$emit('jerry-event',2);
}
},
mounted:function(){
//监听事件
eventHub.$on('tom-event',(val)=>{
this.num+=val;
})
}
});
//组件test-jerry
Vue.component("test-jerry", {
data() {
return {
num: 0
}
},
template: `
Jerry:{
{num}}
`,
methods: {
handle:function(val){
eventHub.$emit('tom-event',1);
}
},
mounted:function(){
//监听事件
eventHub.$on('jerry-event',(val)=>{
this.num+=val;
})
}
});
var vm=new Vue({
el:'#app',
data:{
},
methods: {
//注销事件
handle:function(){
eventHub.$off('tom-event');
eventHub.$off('jerry-event');
}
},
});
script>
<div id="app">
<input type="button" value="show" @click="show">
<h3 id="myh3" ref="myh3">今天天气真好!h3>
<com1 ref="com1">com1>
div>
<template id="tmp1">
<div>
<h1>这是子组件h1>
div>
template>
<script type="text/javascript">
//定义一个自变量类型的组件模板对象
var com1={
template: '#tmp1',//通过指定id,加载对应的template元素中的内容,当做组件的HTML结构
methods:{
myclick(){
console.log('子组件事件')
}
}
}
var vm = new Vue({
el: '#app',
data: {
msg:'这是父组件中的值'
},
methods:{
show:function () {
/*通过this.$refs.元素名称进行访问*/
console.log(this.$refs.myh3.innerText)
this.$refs.com1.myclick()
}
},
/*定义子组件*/
components:{
com1
}
})
script>
<div id="app">
<router-link to="/login" tag="span">登录router-link>
<router-link to="/register">注册router-link>
<router-view>router-view>
div>
<script type="text/javascript">
//登录组件模板对象
var login={
template: '登录组件
'
}
//登录组件模板对象
var register={
template: '注册组件
'
}
/*第二步创建VueRouter实例*/
//创建一个路由对象,当导入一个vue-router包后,在window全局对象中,就有一个路由的构造函数,叫做VueRouter
var routerObj=new VueRouter({
/*路由匹配规则数组,注意是routes*/
routes:[
/**
* 每个路由匹配规则都是一个对象,每个对象必须有2个属性
* 属性1 path,表示监听那个路由链接地址
* 属性2 component,表示对应前面path路由匹配的对应组件,且必须是组件模板对象,不能是组件引用名称
*/
{
path:'/login',component:login},
{
path:'/register',component:register}
]
})
var vm = new Vue({
el: '#app',
data: {
},
router: routerObj//将路由匹配对象,注册到vue实例上,用来监听URL地址的变化,然后展示对应的组件
})
script>
上面代码中需要注意,使用点击超链接流程是:超链接改变请求地址的hash,然后在根据请求地址请求匹配对应的组件
在上面的案例中第一次进入页面应该展示登录组件比较合理,这个时候可以采用
{path:'/',component:login}
但是地址栏上#/显示的却是登录组件,会给用户带来困惑
所以我们可以使用vue-router提供的redirect
{path:'/',redirect:'/login'},
通过上面案例,点击 router-link会自动在该控件上添加类:router-link-active
该类是由VueRouter实例中的linkActiveClass指定的所以修改控件点击样式有2种方式
<style>
.myactive{
color:red;
}
/*方式二重写默认样式的router-link-active*/
.router-link-active{
color:blue;
}
style>
<div id="app">
<router-link to="/login" tag="span">登录router-link>
<router-link to="/register">注册router-link>
<router-view>router-view>
div>
<script type="text/javascript">
//登录组件模板对象
var login={
template: '登录组件
'
}
//登录组件模板对象
var register={
template: '注册组件
'
}
/*第二步创建VueRouter实例*/
//创建一个路由对象,当导入一个vue-router包后,在window全局对象中,就有一个路由的构造函数,叫做VueRouter
var routerObj=new VueRouter({
/*路由匹配规则数组,注意是routes*/
routes:[
/**
* 每个路由匹配规则都是一个对象,每个对象必须有2个属性
* 属性1 path,表示监听那个路由链接地址
* 属性2 component,表示对应前面path路由匹配的对应组件,且必须是组件模板对象,不能是组件引用名称
*/
{
path:'/',component:login},
//{path:'/',redirect:'/login'},
{
path:'/login',component:login},
{
path:'/register',component:register}
],
/*方式一自定义指定样式*/
//linkActiveClass:'myactive'
})
var vm = new Vue({
el: '#app',
data: {
},
router: routerObj//将路由匹配对象,注册到vue实例上,用来监听URL地址的变化,然后展示对应的组件
})
script>
<router-link to="/login?id=10" tag="span">登录router-link>
在代码中输出路由传递的参数
//登录组件模板对象
var login={
template: '登录组件--{
{$route.query.id}}
',
created(){
//组件生命周期钩子函数
console.log(this.$route.query.id)
}
}
vue-router提供了一套参数正则匹配
/:id/:name
在传参时,通过/12/zhagnsan
在vue中的Router中的params中会生成
id:12
name:zhagnsan
修改代码如下
<router-link to="/login/12/ls">登录router-link>
<script>
//登录组件模板对象
var login={
template: '登录组件--{
{$route.params.id}}--{
{$route.params.name}}
',
created(){
//组件生命周期钩子函数
console.log(this.$route.params.id)
console.log(this.$route.params.name)
}
}
<!--在路由匹配规则中使用:名称-->
{
path:'/login/:id/:name',component:login}
script>
<div id="app">
<router-link to="/account">accountrouter-link>
<router-view>router-view>
div>
<template id="tmp1">
<div>
<h1>这是Account组件h1>
<router-link to="/account/login">登录router-link>
<router-link to="/account/register">注册router-link>
<router-view>router-view>
div>
template>
<script type="text/javascript">
var account={
template:'#tmp1'
}
//登录组件模板对象
var login={
template: '登录组件
',
}
//登录组件模板对象
var register={
template: '注册组件
',
}
/*第二步创建VueRouter实例*/
//创建一个路由对象,当导入一个vue-router包后,在window全局对象中,就有一个路由的构造函数,叫做VueRouter
var routerObj=new VueRouter({
/*路由匹配规则数组,注意是routes*/
routes:[
/**
* 每个路由匹配规则都是一个对象,每个对象必须有2个属性
* 属性1 path,表示监听那个路由链接地址
* 属性2 component,表示对应前面path路由匹配的对应组件,且必须是组件模板对象,不能是组件引用名称
*/
{
path:'/account',
component:account,
/*children子路由*/
children:[
/*子路由的path前面不要带 / ,否则永远从根路径开始请求*/
{
path:'login',component:login},
{
path:'register',component:register}
]
}
],
/*方式一自定义指定样式*/
//linkActiveClass:'myactive'
})
var vm = new Vue({
el: '#app',
data: {
},
router: routerObj//将路由匹配对象,注册到vue实例上,用来监听URL地址的变化,然后展示对应的组件
})
script>
<div id="app">
<router-view>router-view>
<router-view name="left">router-view>
<router-view name="main">router-view>
div>
<script type="text/javascript">
var header={
template:'头组件
'
}
//登录组件模板对象
var left={
template: '左侧组件
',
}
//登录组件模板对象
var main={
template: '右侧组件
',
}
/*第二步创建VueRouter实例*/
//创建一个路由对象,当导入一个vue-router包后,在window全局对象中,就有一个路由的构造函数,叫做VueRouter
var routerObj=new VueRouter({
/*路由匹配规则数组,注意是routes*/
routes:[
{
path:'/',
/*注意这里是components*/
components:{
/*左边名称会自动添加引号*/
default:header,
left:left,
left:main
}
}
],
/*方式一自定义指定样式*/
//linkActiveClass:'myactive'
})
var vm = new Vue({
el: '#app',
data: {
},
router: routerObj//将路由匹配对象,注册到vue实例上,用来监听URL地址的变化,然后展示对应的组件
})
script>
<div id="app">
<input type="text" v-model="firstname">+
<input type="text" v-model="lastname">
<input type="text" v-model="fullname">
div>
<script type="text/javascript">
var vm = new Vue({
el: '#app',
data: {
firstname:'',
lastname:'',
fullname:''
},
watch:{
/*watch可以监视data中指定数据的变化,然后触发这个watch中对应的function处理函数*/
firstname: function (newVal,oldVal) {
this.fullname=newVal+'-'+this.lastname
},
lastname: function (newVal,oldVal) {
this.fullname=newVal+'-'+this.lastname
},
}
})
script>
<div id="app">
<input type="text" v-model="firstname">+
<input type="text" v-model="lastname">
<input type="text" v-model="fullname">
div>
<script type="text/javascript">
var vm = new Vue({
el: '#app',
data: {
firstname: '',
lastname: ''
},
/*
* 在computed中可以定义一些属性,叫做【计算属性】,计算属性的本质就是一个方法
* 计算属性可以直接当做属性来使用,并不会把计算属性当做方法来调用
* 计算属性function内部如果用到了data数据,只要其中发生了变化,就会立即重新计算。
* 计算属性的求值结果会被缓存起来,方便下次使用。
* */
computed: {
'fullname': function f() {
return this.firstname+'-'+this.lastname
}
}
})
script>
WebPack可以看做是模块打包机:它做的事情是,分析你的项目结构,找到JavaScript模块以及其它的一些浏览器不能直接运行的拓展语言(Scss,TypeScript等),并将其转换和打包为合适的格式供浏览器使用。
全局安装
npm install -g webpack
局部安装
npm install --save-dev webpack
npm init
输入这个命令后,终端会提出一系列问题,一般默认即可,也可以使用npm init -y。在项目目录下,自动创建package.json 文件。
package.json文件已经就绪,在项目中安装webpack依赖包
npm install --save-dev webpack
现在需要实现一个功能:页面显示多个列表行,奇数行和偶数行背景颜色不同
index.html
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>首页title>
head>
<body>
<ul>
<li>这是第1个lili>
<li>这是第2个lili>
<li>这是第3个lili>
<li>这是第4个lili>
<li>这是第5个lili>
<li>这是第6个lili>
<li>这是第7个lili>
<li>这是第8个lili>
<li>这是第9个lili>
<li>这是第10个lili>
ul>
body>
html>
项目安装jquery
npm install jquery --save 缩写
npm i jquery -S
补充npm i 安装命令中的 -g -D -S的区别
https://blog.csdn.net/qq_32202099/article/details/100005445
main.js
//项目的js入口文件
//导入jquery
import $ from 'jquery'
// const $ = require('jquery')
$(function(){
$('li:odd').css('backgroundColor','black')
$('li:even').css('backgroundColor',function(){
return '#'+'D97634'
})
})
因为在main.js中使用了import命令,这是ES6代码,浏览器解析不了。所以需要使用webpack继续解析成对应js文件
webpack .\src\main.js .\dist\bundle.js
在index.js文件中引入这个bundle.js文件即可。
当修改main.js文件内容时,需要重新手运行webpack .\src\main.js .\dist\bundle.js比较麻烦。现在引入webpack配置文件
在项目根目录下创建 webpack.config.js
const path=require('path')
//这个配置文件,起始就是一个JS文件,通过Node中的模块,向外暴露一个配制对象
module.exports={
entry: path.join( __dirname ,'./src/main.js'),//入口,要使用webpack打包那个文件
output:{
path: path.join(__dirname,'./dist'),//指定打包好的文件,输出到哪个目录中去
filename: 'bundle.js'//指定输出文件的名称
}
}
现在再次修改main.js文件后,可以直接运行webpack命令即可
修改main.js自动编译
本地安装 webpack-dev-server插件,实现自动打包编译功能
npm i webpack-dev-server -D
因为是本地安装,不能在终端直接使用 webpack-dev-server命令,所以需要在package.json中配置
"scripts": {
....,
"dev": "webpack-dev-server"
},
在命令行中可以直接运行
npm run dev
注意: 运行webpack-dev-server生成的bundle.js是在内存中的,路径是/bundle.js,所以需要修改一下index.js中的引用。
webpack-dev-server常用参数配置方式一
在package.json中配置,方便
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"dev": "webpack-dev-server --open --port 3000 --contentBase src --hot"
},
–open:启动webpack-dev-server自动打开浏览器
–port 3000 :端口号
–contentBase src:默认打开网页目录
– hot:热更新,不用每次都生成全新的bundle.js文件
webpack-dev-server常用参数配置方式一
在webpack.config.js中配置,比较麻烦
直接查看js文件
const path=require('path')
//启动热更新的第二步
const webpack=require('webpack')
//这个配置文件,起始就是一个JS文件,通过Node中的模块,向外暴露一个配制对象
module.exports={
entry: path.join( __dirname ,'./src/main.js'),//入口,要使用webpack打包那个文件
output:{
path: path.join(__dirname,'./dist'),//指定打包好的文件,输出到哪个目录总去
filename: 'buddle.js'//指定输出文件的名称
},
devServer:{
//这是配置dev-server 命令参数的第二种形式,相对来说,这种方式麻烦一些
// --open --port 3000 --contentBase src --hot
open:true,//自动打开浏览器
port:3000,//设置启动时运行端口
contentBase:'src',//指定托管的跟目录
hot:true//启动热更新的第一步
},
plugins:[//配置插件的结点
//启动热更新第三步
new webpack.HotModuleReplacementPlugin(),
]
}
安装配置 html-webpack-plugin
自动在内存中根据指定页面生成一个内存页面
安装 npm i html-webpack-plugin -D
配置
const path=require('path')
//启动热更新的第二步
const webpack=require('webpack')
//导入内存中生成HTML页面的插件
//只要是插件都需要放到 plugins结点中
//这个插件的两个作用:
// 1. 自动在内存中根据指定页面生成一个内存页面
// 2. 自动,把打包好的bundle.js追加到页面中去
const htmlWebpackPlugin=require("html-webpack-plugin")
//这个配置文件,起始就是一个JS文件,通过Node中的模块,向外暴露一个配制对象
module.exports={
entry: path.join( __dirname ,'./src/main.js'),//入口,要使用webpack打包那个文件
output:{
path: path.join(__dirname,'./dist'),//指定打包好的文件,输出到哪个目录总去
filename: 'buddle.js'//指定输出文件的名称
},
devServer:{
//这是配置dev-server 命令参数的第二种形式,相对来说,这种方式麻烦一些
// --open --port 3000 --contentBase src --hot
open:true,//自动打开浏览器
port:3000,//设置启动时运行端口
contentBase:'src',//指定托管的跟目录
hot:true//启动热更新的第一步
},
plugins:[//配置插件的结点
//启动热更新第三步
new webpack.HotModuleReplacementPlugin(),
new htmlWebpackPlugin({
template: path.join(__dirname,'./src/index.html'),//指定模板页面,将来会根据指定的页面,去内存生成内存中的页面
filename: 'index.html'//指定生成页面的名称
})
]
}
运行 npm run dev,会访问内存中生成的index.html页面,页面会自动在body末尾添加内存中bundle.js文件的应用。
处理css文件的第三方loader
webpack默认只能打包处理JS类型的文件,处理非JS类型的文件,需要手动安装一些合适的第三方loader加载器。处理css文件,需要安装style-loader、css-loader。
npm i style-loader css-loader -D
在webpack.config.js配置文件中,新增配置结点 module对象,在这个module对象身上,有一个rules属性,这个属性是一个数组,存放所有第三方文件的匹配和处理规则。
module:{
rules:[
{
test:/\.css$/,use:['style-loader','css-loader']},//配置处理css文件的第三方loader规则
]
}
处理less文件的第三方loader
npm i less-loader -D
出现没有安装的依赖,需要继续安装
{
test:/\.less$/,use:['style-loader','css-loader','less-loader']},//处理less文件的第三方loader规则
处理scss文件的第三方loader
npm i sass-loader -D
出现没有安装的依赖,需要继续安装
{
test:/\.less$/,use:['style-loader','css-loader','sass-loader']},//处理scss文件的第三方loader规则
处理图片文件的第三方loader
npm i url-loader file-loader -D
其中file-loader是url-loader的依赖包,出现没有安装的依赖,需要继续安装
{
test:/\.(jpg|png|bmp|jpeg|gif)$/,use:'url-loader'},//处理图片文件的第三方loader规则
loader设置参数:
{
test:/\.(jpg|png|bmp|jpeg|gif)$/,use:'url-loader?limit=7631&name=[name].[ext]'}
其中limit给定值是图片的大小,单位是byte,引用的图片如果大于等于给定值,则不会转成base64格式字符串,否则转成base64格式字符串
name=[name].[ext]:[name] 代表之前什么名,转换后还是什么名;.[ext]之前什么后缀名,转换后还是什么后缀名。
如果希望前面加上hash:name=[hash:8]-[name].[ext]:[name]:天面添加8位hash值。
处理字体图标的第三方loader
使用的loader还是url-loader。这里引用bootstrap中的字体图标。
npm i [email protected] -S
注意这个案例中需要引入[email protected]
到bootstrap官网上找一个组件:
<span class="glyphicon glyphicon-search" aria-hidden="true">span>
在main.js中引入bootstrap.css依赖
//如果通过路径形式引入node_modules中的相关文件,可以省略路径前面的node_modules这一层目录。默认会取node_modules中查找
import 'bootstrap/dist/css/bootstrap.css'
在webpack.config.js中添加匹配处理规则
{
test:/\.(|eot|svg|ttf|woff|woff2)$/,use:'url-loader'},//处理文字文件的第三方loader规则
注意:json文件中不能有注释
webpack中babel配置
在webpack中,默认只能处理一部分ES6的新语法,一些更高级的ES6语法或ES7语法需要借助第三方loader将其处理为低级语法后,再把结果交给webpack去打包到bundle.js中。
安装两套包,安装Babel的loader功能
在webpack.config.js文件中配置匹配规则
{test:/.js&/,use:'babel-loader',exlude:/node_modules/}
exlude用来排除对应的文件包,只需要解析我们自己写的js文件。
{
"presets":["env","stage-0"],
"plugins":["transform-runtime"]
}
vue中render函数渲染组件
<div id="app">
div>
<script>
var login={
template:'这是登陆组件
'
}
var vm=new Vue({
el:'#app',
data:{
},
methods:{
},
//createElements是一个方法,调用它,能够把指定的组件模板渲染为HTML结构
render:function(createElements){
//注意,这里的return结果会替换页面中el指定的那个容器
return createElements(login)
}
});
script>
安装vue
npm i vue -D
在main.js中引入vue
//注意:在webpack中,使用import vue from 'vue'导入的Vue构造函数,功能不完整,
//只提供了runtime-only的方式,并没有提供像网页中那样使用方式
//方式一
import Vue from '../node_modules/vue/dist/vue.js'
//回顾包的查找规则:
//1. 查找项目根目录有没有node_modules文件夹
//2. 在node_modules中根据包名,找对应的vue文件夹
//3. 在vue文件夹中找一个叫 package.json的包配置文件
//4. 在package.json 文件中,查找一个main属性【main属性指定了这个包在被加载的时候,入口文件】
var login={
template:'这是登陆组件
'
}
var vm=new Vue({
el:'#app',
data:{
},
methods:{
},
//createElements是一个方法,调用它,能够把指定的组件模板渲染为HTML结构
render:function(createElements){
//注意,这里的return结果会替换页面中el指定的那个容器
return createElements(login)
}
});
引入vue的第二种方式
main.js
//方式二
import Vue from 'vue'
在webpack.config.js
resolve:{
alias:{
"vue$":"vue/dist/vue.js"
}
}
使用vue的runtime-only模式
在runtime-only模式,需要把vue模板template放到对应的.vue文件中
在src目录下建立login.vue文件
/* 模板 */
<template>
<div>
<h1>这是登陆组件h1>
div>
template>
/* 业务逻辑 */
<script>script>
/* 样式 */
<style>style>
安装配置处理vue文件的loader
npm i vue-loader -D
在webpack.config.js文件中配置插件
const VueLoaderPlugin = require('vue-loader/lib/plugin');
plugins:[//配置插件的结点
// make sure to include the plugin for the magic
new VueLoaderPlugin()
],
main.js
import Vue from 'vue'
import login from './login.vue'
var vm=new Vue({
el:'#app',
data:{
},
methods:{
},
render:function(createElements){
return createElements(login)
}
});
export default和export使用方法
在login.vue组件文件中,添加数据变量
<template>
<div>
<h1>这是登陆组件-----{
{
msg}}----{
{
title}}</h1>
</div>
</template>
<script>
export default{
data(){
//注意组件中的data必须是function
return {
msg:'123',
title:'小星星'
}
},
methods:{
show(){
console.log("调用了login.vue 中的show方法");
}
}
}
</script>
<style></style>
在src目录下新建test.js
//再Node中向外暴露成员的形式:
//module.exports和exports暴露成员
//var 名称=require('模块标识符') 接收成员
//在ES6中,使用export default 和export 向外暴露成员;使用import 模块名称 from '模块路径'
//一个模块 只能使用export default向外暴露一次
export default{
name:'ly',
sex:'男'
}
//export可以多次使用,并且可以和export default 一起使用
export var title='大猩猩'
在main.js中引入test.js文件
//接收,其中export需要使用{}来接收,称为【按需导出】,使用as可以换名
import person,{
title as title11} from './test.js'
console.log(person)
console.log(title11)
npm i vue-router -S
在src目录下建立main文件夹,文件夹中建立Account.vue和GoodsList.vue
/* Account.vue */
<template>
<div>
<h1>这是account组件</h1>
</div>
</template>
<script>
</script>
<style></style>
/* GoodsList.vue */
<template>
<div>
<h1>这是goodslist组件</h1>
</div>
</template>
<script>
</script>
<style></style>
在src下建立新文件login.vue
<template>
<div>
<h1>这是登陆组件</h1>
<router-link to="/account">Account</router-link>
<router-link to="/goodslist">GoodsList</router-link>
<router-view></router-view>
</div>
</template>
<script>
</script>
<style></style>
在main.js中引入vue-router
//项目的js入口文件
import Vue from 'vue'
//1. 导入vue-router包
import VueRouter from 'vue-router'
import login from './login.vue'
import account from './main/Account.vue'
import goodslist from './main/GoodsList.vue'
//2. 手动安装VueRouter
Vue.use(VueRouter)
//3. 创建路由对象
var router = new VueRouter({
routes:[
{
path:'/',redirect:'/account'},
{
path:'/account',component:account},
{
path:'/goodslist',component:goodslist}
]
})
var vm=new Vue({
el:'#app',
data:{
},
methods:{
},
render:function(createElements){
return createElements(login)
},
router
});
在Vue组件中的style中设置样式,默认是全局效果
<style>
div{
font-style: italic;
}
style>
通过添加scoped属性来限制为当前组件的样式
<style scoped>
div{
font-style: italic;
}
style>
scoped属性是通过属性选择器的方式起作用的
在style中可以使用less和scss文件格式通过lang属性来指定
<style lang="scss" scoped>
body{
div{
font-style: italic;
}
}
style>
基本原则,把路由配置部分的代码从main.js中抽离出来,放到一个和mian.js同级的文件 router.js文件中。
变异方法:修改原始数据
push()
pop()
shift()
unshift()
splice()
sort()
reverse()
替换数组:生成新的数组
filter()
concat()
slice()
Vue数组响应式变化
Vue.set(vm.items,indexOfItem,newValue)
vm.$set(vm.item,indexOfItem,newValue)
参数1:数组名称
参数2:数组索引
参数3:要处理的值
<div id="app">
<li :key="index" v-for="(item,index) in list">{
{item}}li>
div>
<script>
var vm=new Vue({
el:'#app',
data: {
list:["apple","orange","lemon"]
},
});
//修改在页面无响应
//vm.list[1]="pear";
//响应方式1
//Vue.set(vm.list,1,'pear');
vm.$set(vm.list,1,'pear');
script>
通过上面两个方式也可以向对象中添加值
Vue.set(vm.object,‘key’,value)
在子组件内使用元素可以为该子组件开启一个插槽,在父组件模板中,插入子组件标签内的所有内容将替代子组件的标签及它的内容。
<div id="app">
<alert-box>有一个警告alert-box>
<alert-box>alert-box>
div>
<script>
//组件test-jerry
Vue.component("alert-box", {
template: `
Error:
默认值
`
});
var vm = new Vue({
el: '#app',
data: {
}
});
script>
给组件中的元素指定一个name可以在父组件中指定内容填充到子组件中,父组件中没有对应的name会填充到匿名slot中。
<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>Documenttitle>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js">script>
<style>
.header{
color: red;
}
.footer{
color: blue;
}
style>
head>
<body>
<div id="app">
<base-layout>
<template slot="header">
<div>
<p slot="header">标题信息1p>
<p slot="header">标题信息2p>
div>
template>
<p >主要内容1p>
<p >主要内容2p>
<template slot="footer">
<div>
<p slot="footer">底部信息1p>
<p slot="footer">底部信息2p>
div>
template>
<p >主要内容3p>
base-layout>
div>
<script>
Vue.component("base-layout",{
template:`
`
})
var vm=new Vue({
el:'#app'
})
script>
body>
html>
上面案例运行结果图:
应用场景:父组件对子组件的内容进行加工处理
<div id="app">
<fruit-list :list='list'>
<template slot-scope='slotProps'>
<strong v-if="slotProps.item.id==1">{
{slotProps.item.name}}strong>
<span v-else>{
{slotProps.item.name}}span>
template>
fruit-list>
div>
<script>
Vue.component("fruit-list",{
props:['list'],
template:`
{
{item.name}}
`
})
var vm=new Vue({
el:'#app',
data:{
list:[
{
id:1,
name:'apple'
},
{
id:2,
name:'orange'
},
{
id:3,
name:'banana'
}
]
}
})
script>
实例化Promise对象,构造函数中传递函数,该函数用于处理异步任务。
resolve和reject两个参数用于处理成功和失败两种情况,并通过p.then获取处理结果。
<script>
var p=new Promise(function(resolve,reject){
var flag=true;
if(flag){
resolve('hello world!');
}else{
reject('错误结果');
}
});
p.then(function(ret){
//从resolve处理逻辑
console.log(ret);
},function(ret){
//reject处理逻辑
console.log(ret);
});
script>
这里需要了解一下原生ajax请求步骤
<script>
//基于Promise处理Ajax请求
function queryData(url){
var p=new Promise(function(resolve,reject){
var xhr=new XMLHttpRequest();
xhr.onreadystatechange=function(){
if(xhr.readyState!=4) return;
if(xhr.readyState==4&& xhr.status==200){
//处理正常的情况
resolve(xhr.responseText);
}else{
reject('服务器错误');
}
}
xhr.open('get',url);
xhr.send(null);
});
return p;
}
queryData(url1)
.then(function(data){
console.log(data);
//小技巧:返回下一个需要请求的对象,可以直接在后面使用.then()方法
return queryData(url2);
})
.then(function(data){
console.log(data);
})
script>
then参数中的函数返回值
返回的实例对象会调用接下来的then,就是上面案例所示。
返回的普通值会直接传递给下一个then(),通过then()参数中的函数来接收该值,因为没有返回Promise对象,默认会创建一个Promise对象,所以依旧可以调用then()方法。
queryData(url)
.then(function(data){
console.log(data);
//小技巧:返回下一个需要请求的对象,可以直接在后面使用.then()方法
return "hello";
})
.then(function(data){
console.log(data);
})
Promise的实例方法
p.then():得到异步任务的结果
p.catch():获取异常信息
p.finally():成功与否都会执行
<script>
var p=new Promise(function(resolve,reject){
var flag=false;
if(flag){
resolve('hello world!');
}else{
reject('错误结果');
}
});
p.then(function(ret){
//从resolve处理逻辑
console.log('then:'+ret);
})
//当执行reject时,会执行,相当于then方法中第二个函数
.catch(function(data){
console.log("catch:"+data);
})
//无论成功失败,都会执行
.finally(function(){
console.log('finally');
})
script>
Promise中对象方法
Promise.all()并发处理多个异步任务,所有任务都执行完成才得到结果
Promise.race()并发处理多个异步任务,只要一个任务完成就得到结果,其他的异步任务也会执行,但是不获取结果。
//获取p1,p2,p3对应的返回结果
Promise.all([p1,p2,p3]).then((result)=>{
console.log(result)
})
//只获取p1对应的返回结果
Promise.race([p1,p2,p3]).then((result)=>{
console.log(result)
})
fetch(url).then(function(data){
//返回Promise对象,用于获取后台返回的数据
return data.text();
})
//Promise通过then方法,来处理其中的数据
.then(function(data){
console.log(data);
})
常用配置选项
method(String):HTTP请求方法,默认为Get(POST、PUT、DELETE)
body(String):http请求的参数
header(Object):http请求头,默认为{}
fetch(url,{
method:'get'
}).then(function(data){
//返回Promise对象,用于获取后台返回的数据
return data.text();
})
//Promise通过then方法,来处理其中的数据
.then(function(data){
console.log(data);
})
Get和Delete方式传参数一般有两种:?xxx=‘xxx’&yyy=‘yyy’,vue通过 query获取
/:id/name ,vue中通过params获取
post和put传参
//字符串格式
fetch(url,{
method:'post',
body:'name=lisi&pwd=123',
headers:{
'Content-Type':'application/x-www-form-urlencoded'
}
}).then(function(data){
//返回Promise对象,用于获取后台返回的数据
return data.text();
})
//Promise通过then方法,来处理其中的数据
.then(function(data){
console.log(data);
})
//json格式
fetch(url,{
method:'post',
body:JSON.stringify({
name:'lisi',
pwd:'123'
}),
headers:{
'Content-Type':'application/json'
}
}).then(function(data){
//返回Promise对象,用于获取后台返回的数据
return data.text();
})
//Promise通过then方法,来处理其中的数据
.then(function(data){
console.log(data);
})
查看版本
vue -V
安装
npm install -g @vue/cli 1).使用命令创建Vue项目
命令:vue create my-project
选择Manually select features(选择特性以创建项目)
勾选特性可以用空格进行勾选。
是否选用历史模式的路由:n
ESLint选择:ESLint + Standard config
何时进行ESLint语法校验:Lint on save
babel,postcss等配置文件如何放置:In dedicated config files(单独使用文件进行配置)
是否保存为模板:n
使用哪个工具安装包:npm
基于ui界面创建Vue项目
命令:vue ui
在自动打开的创建项目网页中配置项目信息。
基于2.x的旧模板,创建Vue项目
npm install -g @vue/cli-init
vue init webpack my-project
node_modules:依赖包目录
public:静态资源目录
src:源码目录
src/assets:资源目录
src/components:组件目录
src/views:视图组件目录
src/App.vue:根组件
src/main.js:入口js
src/router.js:路由js
babel.config.js:babel配置文件
.eslintrc.js: eslint语法配置文件
配置项目启动自动打开浏览器及端口:
"vue":{
"devServer":{
"port":8888,
"open":true
}
}
module.exports={
devServer:{
//自动打开浏览器
open:true,
port:8878
}
}
注意: 两种配置方式只能同时使用一种
Element-UI:一套为开发者、设计师和产品经理准备的基于Vue 2.0的桌面组件库
npm i element-ui -S
//导入element-ui库
import ElementUI from 'element-ui'
//导入element-ui相关样式
import 'element-ui/lib/theme-chalk/index.css'
//配置Vue插件
Vue.use(ElementUI)
运行vue ui命令,打开图形化界面
通过vue项目管理器,进入具体的项目配置面板
点击插件->添加插件,进入插件查询面板
搜索vue-cli-plugin-element并安装
配置插件,实现按需导入。