2020-3-9-vue使用

快速开始、挂载点el、数据对象data、方法对象methods、渲染标识、插值表达式闪烁问题、过滤器、自定义全局按键修饰符、人员管理实现案例、自定义指令、声明周期函数、Vue-resource向服务端请求数据、用户管理案例、组件、ref获取dom节点、路由、watch的监视功能、computed存放组合计算后的变量、nrm的使用、render函数渲染、wepack中使用vue

快速开始

var app = new Vue({
  el: '#app',
  data: {
    message: 'Hello Vue!'
  }
})
{% raw %}
<div id="app">
  {{ message }}<!--Hello Vue!-->
</div>
{% endraw %}

其中,el为挂载点,data为数据对象,methods为方法对象


挂载点el

vue命中元素及其内部的后代元素,不可将html、body作为挂载对象,可通过id、class、tag作为选择挂载点


数据对象data

定义数据变量,模板中直接使用变量便可取到变量的值。但在methods中,需要在变量前加上this.


方法对象methods

定义方法


渲染标识

1文本

v-text和v-html,两者的区别是,v-text的值不会被浏览器二次渲染,v-html则会

2事件

v-on:eventname,其中eventname可以是click(点击),mouseoner(鼠标移入),dbclick(双击),值为methods里的方法变量

可以将事件进行简写,v-on:click可简写为@click,其他类似

事件修饰符

修饰符 功能
.stop 阻止冒泡
.prevent 阻止默认事件
.capture 实现捕获触发事件机制
.self 实现只点击当前元素时,才触发事件
.once 只能触发一次事件处理函数

3显示隐藏

v-if,v-show,值为布尔值,区别为前者会进行dom操作,后者是样式操作

4设置元素属性

v-bind:attr,其中attr可以是class或其他赋予标签的属性

可以进行简写,v-bind:class可简写为:class,其他类似

{% raw %}
<!--通过类名设置样式-->
<h1 class='red thin'>天生我材必有用,千金散尽还复来。</h1>
<h1 :class="['red','thin']">天生我材必有用,千金散尽还复来。</h1>
<h1 :class="[flag?'active':'']">天生我材必有用,千金散尽还复来。</h1><!--flag为布尔值-->
<h1 :class="{'active':flag}">天生我材必有用,千金散尽还复来。</h1>
{% endraw %}
{% raw %}
<!--通过style属性设置样式-->
<h1 :style="{color:'red'}">北国风光,千里冰封,万里雪飘。</h1>
<h1 :style='[obj1,obj2]'>北国风光,千里冰封,万里雪飘。</h1><!--obj1,obj2都是data里的变量对象-->
{% endraw %}

5循环

v-for,值为循环语句如item of arr,将循环标签内包含item的标签

{% raw %}
<ul v-for="item of arr">
    <li>{{item}}</li>
</ul>
{% endraw %}

6双向数据绑定

v-model,值为data里的变量,但只可用在表单元素中


插值表达式闪烁问题

标签内包含插值表达式(如{{item}}),会在渲染时出现闪烁问题,通过v-cloak可以解决

{% raw %}
<style>
[v-cloak]{
	display: none;
}
</style>
<p v-cloak>
    {{name}}
</p>
{% endraw %}

过滤器

1全局过滤器

{% raw %}
<p>{{msg|msgFormat}}</p>
<script>
Vue.filter('msgFormat',function(msg){
    return msg.replace(/单纯/g,'邪恶')
})
</script>
{% endraw %}

2局部过滤器

var app1=new({
    el:'#app1',
    data:{},
    methods:{},
    filters:{
        msgFormat:function(msg){
            return msg.replace(/单纯/g,'邪恶')
        }
    }
})

自定义全局按键修饰符

vue.config.keyCodes.f2=113

人员管理实现案例

实现人员添加、删除、搜索功能

{% raw %}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        [v-cloak]{
            display: none;
        }
    </style>
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <script>
    window.onload=function(){
        var app=new Vue({
            el:'#app',
            data:{
                id:'',
                name:'',
                age:'',
                sex:'',
                search:'',
                list:[{id:'1',name:'zhang',age:'20',sex:'male'}]
            },
            methods:{
                doadd(){//添加
                    if(!this.name||!this.age||!this.sex){
                        return
                    }
                    let dic={id:this.id,name:this.name,age:this.age,sex:this.sex}
                    this.list.push(dic)
                },
                del(i){//删除
                    this.list.splice(i,1)
                },
                dosearch(){//搜索
                    return this.list.filter(item=>{
                        if(item.name.includes(this.search)){
                            return item
                        }
                    })
                }
            }
        })
    }
    </script>
</head>
<body>
    <div id="app">
        <div class="container">
            <p></p>
            <div class="card">
                <div class="card-body">
                    <form class="form-inline mx-sm-3" action="">
                        <div class="form-inline form-group mx-sm-3">
                            <input type="text" class="form-control" v-model='id' placeholder="id">
                        </div>
                        <div class="form-inline form-group mx-sm-3">
                            <input type="text" class="form-control" v-model='name' placeholder="name">
                        </div>
                        <div class="form-inline form-group mx-sm-3">
                            <input type="text" class="form-control" v-model='age' placeholder="age">
                        </div>
                        <div class="form-inline form-group mx-sm-3">
                            <input type="text" class="form-control" v-model='sex' placeholder="sex">
                        </div>
                        <button class="btn btn-info" @click.prevent="doadd">add</button>
                    </form>
                    <br>
                    <form action="" class="form-inline mx-sm-3">
                        <div class="form-inline form-group mx-sm-3">
                            <input type="text" class="form-control" v-model='search' placeholder="search">
                        </div>
                    </form>
                </div>
            </div>
            <p></p>
            <table class="table">
                <thead class="thead-dark">
                  <tr>
                    <th scope="col">Id</th>
                    <th scope="col">Name</th>
                    <th scope="col">Age</th>
                    <th scope="col">Sex</th>
                    <th scope="col">Operating</th>
                  </tr>
                </thead>
                <tbody>
                  <tr v-for='(item,i) in list' v-cloak v-show="search==''">
                    <td scope="row">{{item.id}}</td>
                    <td>{{item.name}}</td>
                    <td>{{item.age}}</td>
                    <td>{{item.sex}}</td>
                    <td><button @click="del(i)" class="btn btn-sm btn-info">delete</button></td>
                  </tr>
                  <tr v-for='(item,i) in dosearch()' v-cloak v-show="search!=''">
                    <td scope="row">{{item.id}}</td>
                    <td>{{item.name}}</td>
                    <td>{{item.age}}</td>
                    <td>{{item.sex}}</td>
                    <td><button @click="del(i)" class="btn btn-sm btn-info">delete</button></td>
                  </tr>
                </tbody>
              </table>
        </div>
      </div>
    
</body>
</html>
{% endraw %}

自定义指令

1全局指令

Vue.directive('color',{
    bind:function(el,binding){
        //样式相关的在这里定义
        el.style.color=binding.value
    },
    inserted:function(){
        //js行为相关操作在这里定义
    },
    updated:function(){
        
    }
})
<input type="text" class="form-control" v-model='search' placeholder="search" v-color="'red'">

2局部指令

var app1=new({
    el:'#app1',
    data:{},
    methods:{},
    filters:{},
    directives:{
        'title':{
            bind:function(el,binding){
                el.title=binding.value
            },
            inserted:function(){  
            },
            updated:function(){
            }
        }
    }
})
<button class="btn btn-info" @click.prevent="doadd" v-title="'button add'">add</button>

3简写

bindupdated做重复操作

Vue.directive('color',function(el,binding){
    el.style.color=binding.value
})

声明周期函数

Vue实例在创建到销毁过程中,各个阶段会触发执行一个函数

var app1=new({
    el:'#app1',
    data:{},
    methods:{},
    /*运行前*/
	beforeCreate(){
        //在实例完全被创建出来之前会执行,data,methods中的数据还未初始化
        console.log("h1")
    },
    created(){
        //实例创建完成执行,data,methods中的数据最早可在这里操作
        console.log("h2")
    },
    beforeMount(){
        //模板在内存中编译完成,但未注入到页面中
        console.log("h3")
    },
    mounted(){
        //实例已完全创建好,如果要操作dom节点,最早在此函数中
        console.log("h4")
    },
    /*运行中*/
    beforeUpdate(){
        //执行时,页面中的数据时旧的,而data中数据时最新的,页面和最新数据尚未同步
        console.log("h5")
    },
    updated(){
        //执行时,页面后data中的数据已保持同步
        console.log("h6")
    },
    /*销毁过程*/
    beforeDestory(){
        //执行时,实例上所有的数据方法均可用,还未真正执行销毁
        console.log("h7")
    },
    destroyed(){
        //执行时,组件中所有的数据和方法已被销毁
        console.log("h8")
    }
})

Vue-resource向服务端请求数据

1引入模块

<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="https://cdn.staticfile.org/vue-resource/1.5.1/vue-resource.min.js"></script>
<!--vue-resource依赖于vue-->

2GET请求

this.$http.get('http://127.0.0.1:3000/userlist'/*地址*/,{params:{name:'zhang'}}/*参数*/).then(data=>{
    this.list=data.body//数据在data.body里
})

3POST请求

this.$http.post('http://127.0.0.1:3000/deluser',{id:this.list[i]._id},{emnlateJSON:true}).then(data=>{
    if(data.body.stat){
        this.list.splice(i,1)
    }
})

4JSONP请求

this.$http.jsonp(this.url).then(result=>{
    console.log(result.body)
})

注意,该模块的GET和POST都不支持跨域,需要跨域使用axios

5启用服务器根设置

//为vue设置根地址,发送请求时不用填写ip地址和端口号,但目标url不可以‘/’开头
Vue.http.options.root='http://127.0.0.1:3000'

//启用emulateJSON选项,使得服务器能够如解析表单一样进行解析
Vue.http.options.emnlateJSON=true

用户管理案例

1前端页面

<!--文件名hello.html-->
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        [v-cloak]{
            display: none;
        }
    </style>
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <script src="https://cdn.staticfile.org/vue-resource/1.5.1/vue-resource.min.js"></script>
    <script>
    window.onload=function(){
       Vue.http.options.root='http://127.0.0.1:3000'
       Vue.http.options.emnlateJSON=true
        var app=new Vue({
            el:'#app',
            delimiters:['$$','$$'],//避免和后端的模板语言发生冲突
            data:{
                id:'',
                name:'',
                age:'',
                sex:'',
                search:'',
                list:[],
            },
            created(){
                this.getdata()
            },
            methods:{
                doadd(){//添加
                    if(!this.name||!this.age||!this.sex){
                        return
                    }
                    let dic={name:this.name,age:this.age,sex:this.sex}
                    this.$http.post('adduser',dic).then(data=>{
                        if(data.body.stat){
                            this.getdata()
                        }
                    })       
                },
                del(i){//删除
                    this.$http.post('deluser',{id:this.list[i]._id}).then(data=>{
                        if(data.body.stat){
                            this.list.splice(i,1)
                        }
                    })       
                },
                dosearch(){//搜索
                    return this.list.filter(item=>{
                        if(item.name.includes(this.search)){
                            return item
                        }
                    })
                },
                getdata(){
                    this.$http.get('userlist').then(data=>{
                    this.list=data.body
                })
                }
            }
            
        })
    }
    </script>
</head>
<body>
    <div id="app">
        <div class="container">
            <div class="card">
                <div class="card-body">
                    <form class="form-inline mx-sm-3" action="">
                        <div class="form-inline form-group mx-sm-3">
                            <input type="text" class="form-control" v-model='name' placeholder="name">
                        </div>
                        <div class="form-inline form-group mx-sm-3">
                            <input type="text" class="form-control" v-model='age' placeholder="age">
                        </div>
                        <div class="form-inline form-group mx-sm-3">
                            <input type="text" class="form-control" v-model='sex' placeholder="sex">
                        </div>
                        <button class="btn btn-info" @click.prevent="doadd" >add</button>
                    </form>
                    <br>
                    <form action="" class="form-inline mx-sm-3">
                        <div class="form-inline form-group mx-sm-3">
                            <input type="text" class="form-control" v-model='search' placeholder="search">
                        </div>
                    </form>
                </div>
            </div>
            <p></p>
            <table class="table">
                <thead class="thead-dark">
                  <tr>
                    <th scope="col">Id</th>
                    <th scope="col">Name</th>
                    <th scope="col">Age</th>
                    <th scope="col">Sex</th>
                    <th scope="col">Operating</th>
                  </tr>
                </thead>
                <tbody>
                  <tr v-for='(item,i) in list' v-cloak v-show="search==''">
                    <td scope="row">$$item._id$$</td>
                    <td>$$item.name$$</td>
                    <td>$$item.age$$</td>
                    <td>$$item.sex$$</td>
                    <td><button @click="del(i)" class="btn btn-sm btn-info">delete</button></td>
                  </tr>
                  <tr v-for='(item,i) in dosearch()' v-cloak v-show="search!=''">
                    <td scope="row">$$item._id$$</td>
                    <td>$$item.name$$</td>
                    <td>$$item.age$$</td>
                    <td>$$item.sex$$</td>
                    <td><button @click="del(i)" class="btn btn-sm btn-info">delete</button></td>
                  </tr>
                </tbody>
              </table>
        </div>
      </div>
    
</body>
</html>

2后端

const koa=require('koa')
const router=require('koa-router')()
const url=require('url')
var querystring=require('querystring')
var render=require('koa-art-template')
var path=require('path')
var axios=require('axios')
var db=require('./db.js')//自封装的mongodb数据库操作类
var bodyParser = require('koa-bodyparser');

var app=new koa()
app.use(bodyParser())


render(app, {
    root: path.join(__dirname, 'views'),   // 视图的位置
    extname: '.html',  // 后缀名
    debug: process.env.NODE_ENV !== 'production'  //是否开启调试模式
});


router.get('/person_m',async(ctx)=>{//获取界面
    await ctx.render('hello',{})
})
router.get('/userlist',async(ctx)=>{//获取用户列表接口
    let result=await db.find('userlist')
    ctx.body=result
})
router.post('/deluser',async(ctx)=>{//删除用户接口
    let id=ctx.request.body['id']
    console.log(id,db.getObjectId(id))
    await db.delete('userlist',{'_id':db.getObjectId(id)}).then((data)=>{
        ctx.body={stat:1}
    })
})
router.post('/adduser',async(ctx)=>{//新增用户接口
    let data=ctx.request.body
    await db.insert('userlist',data).then((data)=>{
        ctx.body={stat:1}
    })
})
app.use(router.routes())//配置路由
app.use(router.allowedMethods())

app.listen(3000)

组件

模块化是从代码角度将项目进行划分,而组件化是从UI角度对项目进行划分

1创建渲染公共组件

1)直接声明方式

var com1=Vue.extend({
    template:'<h1>hahahha</h1>'
  })//构建组件
  Vue.component('mycom1',com1)//将组件注册到全局
<div id="app">
  <mycom1></mycom1><!--将组件渲染出来-->
</div>

2)直接声明方式简化

  Vue.component('mycom2',{
  	template:'<h1>aaaaaa</h1>'
  })//将组件注册到全局

渲染同上

3)template标签方式

<template id="com3"><!--创建标签-->
  <h2>dddddddd</h2>
</template>
  Vue.component('mycom3',{
  	template:'#com3'
  })//将组件注册到全局

渲染同上

2私有组件

注意:私有组件只可访问组件内的data和methods

new Vue({
  el: '#app',
  data: {},
  methods: {},
  components:{//仅当前对象的私有组件
      comp:{
          template:'<div><button @click="add">+</button><p>{{num}}</p></div>',
          data:function(){//必须是返回数据对象的函数
              return {num:0}
          },
          methods:{//组件的内部方法
            add(){
              this.num+=1
            }
          }
      }
  }
})

3组件切换

1)v-if方式切换

<div id="staggered-list-demo">
  <button @click="change">更换组件</button> 
  <mycom1 v-if="flag"></mycom1> 
  <mycom2 v-if="!flag"></mycom2>   
</div>
var com1=Vue.extend({
  template:'<h1>组件1</h1>'
})
Vue.component('mycom1',com1)
Vue.component('mycom2',{
  template:'<h1>组件2</h1>'
})
new Vue({
  el: '#staggered-list-demo',
  data: {
    flag:true,
  },
  methods: {
    change(){
      this.flag=!this.flag
    }
  },
})

2)component标签渲染切换

<style>
  .v-enter,
  .v-leave-to{
    opacity: 0;
    transform: translateY(50px);
  }
  .v-enter-active,
  .v-leave-active{
    transition: all 0.5s ease;
  }
</style><!--特效设定-->
<div id="staggered-list-demo">
  <button @click="change">更换组件</button> 
  <transition mode='out-in'><!--加特效-->
		<component :is="current_comp"></component> 
  </transition>
</div>
var com1=Vue.extend({
  template:'<h1>组件1</h1>'
})
Vue.component('mycom1',com1)
Vue.component('mycom2',{
  template:'<h1>组件2</h1>'
})
new Vue({
  el: '#staggered-list-demo',
  data: {
    num:0,
    current_comp:'mycom1',
    components:['mycom1','mycom2']
  },
  methods: {
    change(){
      this.num++
      this.current_comp=this.components[this.num%2]
    }
  },
})

4组件传值

1)父组件向子组件传值

<div id="staggered-list-demo">
	<mycom1 :fathermsg="msg"></mycom1><!--为子组件设置属性以接收父组件的变量-->
</div>
Vue.component('mycom1',{
	template:'<h1>组件1{{fathermsg}}</h1>',
    props:['fathermsg']//在子组件里注册接收传值的属性名
})
new Vue({
  el: '#staggered-list-demo',
  data: {
    msg:'msg from father',
  }
})

2)子组件触发绑定在自身的父组件的方法

<div id="staggered-list-demo">
	<mycom1 @fnc="dofromfather"></mycom1><!--为子组件绑定自定义事件fnc(埋雷),该事件触发会执行父组件的dofromfather方法-->
</div>
Vue.component('mycom1',{
  template:'<div><button @click="doit">点击调用doit方法</button></div>',
  methods:{
    doit(){
      this.$emit('fnc')//触发子组件身上绑定的自定义事件fnc(引爆地雷),如果自定义事件对应的方法有参数可以作为emit的第二个参数传过去
    }
  }
})
new Vue({
  el: '#staggered-list-demo',
  methods: {
    dofromfather(){
      console.log("this function is from father")
    }
  }
})

ref获取dom节点

<div id="staggered-list-demo">
	<h3  ref='myh3' @click="gogogo">春残何事苦思乡,病里梳头恨最长。</h3>
</div>
new Vue({
  el: '#staggered-list-demo',
  data: {},
  methods: {
    gogogo(){
      console.log(this.$refs.myh3.innerText)
    }
  }
})

路由

1思路

1)导入路由模块

2)创建组件并在app注册

3)创建路由对象,将组件设置入路由中

3)app中注册路由

2代码

<div id="staggered-list-demo"> 
  <transition mode='out-in'><!--动画效果-->
    <router-view></router-view><!--组件会按照路由规则渲染到这里面-->
  </transition>  
  <router-link to='/login' tag='span'>登陆</router-link> 
  <router-link to='/assign' tag='span'>注册</router-link>
  <!--跳转的标签,默认渲染为a标签,这里强制改成span--> 
</div>
const login={
  template:'<div>这是登陆页面</div>',
}
const assign={
  template:'<div>这是注册页面</div>',
}
const routes = [
  {path:'/',redirect:'/login'},//为匹配到则重定向
  { path: '/login', component: login },
  { path: '/assign', component: assign }
]
var router_obj=new VueRouter({
  routes,
  linkActiveClass:'active'//选中的router-link赋予class属性active
})
new Vue({
  el: '#staggered-list-demo',
  components:{//将组件注册到app中,也可以不注册,因为前面在声明路由的时候已经注册了,这里不注册就只可在路由中调用组件,不可在用<login></login>方式调用组件
    login,
    assign
  },
  router:router_obj
})

3传值

1)访问链接为"url?name=1",获取数据this.$route.query.name

2)路由设置为{path:'index/:id'}访问链接为"index/2"时,获取数据this.$route.params.id

4路由嵌套

<!--这里使用了bootstrap的css-->
<template id="bread">
  <div>
    <nav>
      <ol class="breadcrumb">
        <li class="breadcrumb-item active"><router-link to='/bread/home'>Home</router-link></li>
        <li class="breadcrumb-item active"><router-link to='/bread/library'>Library</router-link></li>
      </ol>
    </nav>
    <div class="card">
      <div class="card-body">
        <router-view></router-view>
      </div>
    </div>
  </div>
</template>
<div id="staggered-list-demo">
    <router-link to='/bread'>显示导航</router-link> 
    <router-view></router-view>
</div>
const bread={//一级组件
  template:'#bread'
}
const home={//二级组件
  template:'<div>这是home页面</div>',
}
const library={//二级组件
  template:'<div>这是library页面</div>',
}
const routes = [
  {
    path:'/bread',
    component:bread,
    children:[
    { path: 'home', component: home },//这里不加'/'表示路由地址为'/bread/home',若加'/'则表示路由地址为'/home'
    { path: 'library', component: library }
    ]
  },
]
var router_obj=new VueRouter({
  routes,
})
new Vue({
  el: '#staggered-list-demo',
  router:router_obj
})

5同一路由地址下展示多个组件

<div id="staggered-list-demo">
  <router-view name='comp1'></router-view>
  <router-view name='comp2'></router-view>
  <router-view name='comp3'></router-view>
</div>
const comp1={
  template:'<div>组件1</div>'
}
const comp2={
  template:'<div>组件2</div>',
}
const comp3={
  template:'<div>组件3</div>',
}
const routes = [
  {
    path:'/',
    components:{//放入多个组件,通过router-view的name属性区分
      comp1,comp2,comp3
    }
    },
]
var router_obj=new VueRouter({
  routes,
})
new Vue({
  el: '#staggered-list-demo',
  router:router_obj
})

watch的监视功能

1监视文本框

本质上是监视变量,变量发生变化则会触发watch里对应的方法执行

1)变量监控

<div id="staggered-list-demo">
  <input type="text" v-model='firstname'>
</div>
new Vue({
  el: '#staggered-list-demo',
  data:{
    firstname:''
  },
  watch:{
    'firstname':function(newVal,oldVal){//新值 旧值
      console.log(newVal)
    }
  }
})

2)对象监控

    <div id="staggered-list-demo">
        <input type="text" v-model="person.age">
    </div>
    new Vue({
        el: '#staggered-list-demo',
        data:{
            person:{
                name:"zhanghuan",
                age:22
            }
        },
        watch:{
            person:{
                deep:true,
                handler(val){
                    //val是person对象
                    console.log(val.age)
                }
            }
        }
        })

2路由监视

<div id="staggered-list-demo">
  <router-link to='/login'>login</router-link>
  <router-link to='/assign'>assign</router-link>
  <router-view></router-view>
</div>
var login={
  template:'<div>this is login</div>'
}
var assign={
  template:'<div>this is assign</div>'
}
var router=new VueRouter({
  routes:[
    {path:'/login',component:login},
    {path:'/assign',component:assign}
  ]
})
new Vue({
  el: '#staggered-list-demo',
  watch:{
    '$route.path':function(newVal,oldVal){//监视路由地址,若发生变化会执行函数
      console.log(newVal)
    }
  },
  router
})

computed存放组合计算后的变量

{% raw %}
<div id="staggered-list-demo">
  firstname:<input type="text" v-model='firstname' placeholder="firstname">
  <br>
  lastname:<input type="text" v-model='lastname' placeholder="lastname">
  <br>
  fullname:{{fullname}}<!--访问computed里的变量-->
</div>
{% endraw %}
new Vue({
  el: '#staggered-list-demo',
  data:{
    'firstname':'',
    'lastname':''
  },
  computed:{
    'fullname':function(){//该变量是data中变量的计算结果,会被保存起来,通过变量名便可访问此变量
      return this.firstname+'-'+this.lastname
    }
  }
})

nrm的使用

nrm用于切换npm的镜像下载的地址

1安装

npm install nrm -g

2查看所有可用的镜像地址

nrm ls

3切换镜像地址

nrm use npm

render函数渲染

<div id="app"></div>
var login={
    template:'<h1>this is login</h1>'
}
var app=new Vue({
    el:'#app',
    render:function(createElements){
        return createElements(login)//这里会将login里的模板内容替换掉el指定的容器
    }
})

wepack中使用vue

1传统方式

1)安装

npm i vue -s

2)修改webpack.config.js

const path=require('path')
const htmlwebpackplugin=require('html-webpack-plugin')//导入
module.exports={
	entry:path.join(__dirname,'./src/main.js'),
	output:{
		path:path.join(__dirname,'./dist'),
		filename:'bundle.js'
    },
    plugins:[
        new htmlwebpackplugin({
            template:path.join(__dirname,'./src/index.html'),//源页面
            filename:'index.html'//内存中的页面,将会把bundle.js注入该页面中
        })
    ],
    module:{
        rules:[
            {test:/\.css$/,use:['style-loader','css-loader']},
            {test:/\.less$/,use:['style-loader','css-loader','less-loader']},
            {test:/\.scss$/,use:['style-loader','css-loader','sass-loader']},
            {test:/\.(jpg|png|gif|bmp|jpeg)$/,use:'url-loader'},
            {test:/\.js$/,use:'babel-loader',exclude:/node_modules/}
        ]
    },
    resolve:{//新增
        alias:{
            "vue$":'vue/dist/vue.js'
        }
    }
}

3)main.js文件

import Vue from 'vue'
new Vue({
    el:'#app',
    data:{
        name:'zhanghuan'
    }
})

2另一种方式

1)安装vue及.vue文件的解析工具

npm i vue -s
npm i vue-loader vue-template-compiler -d

2)修改webpack.config.js

const path=require('path')
const htmlwebpackplugin=require('html-webpack-plugin')//导入
const VueLoaderPlugin = require('vue-loader/lib/plugin')//新增
module.exports={
	entry:path.join(__dirname,'./src/main.js'),
	output:{
		path:path.join(__dirname,'./dist'),
		filename:'bundle.js'
    },
    plugins:[
        new htmlwebpackplugin({
            template:path.join(__dirname,'./src/index.html'),//源页面
            filename:'index.html'//内存中的页面,将会把bundle.js注入该页面中
        }),
        new VueLoaderPlugin()//新增
    ],
    module:{
        rules:[
            {test:/\.css$/,use:['style-loader','css-loader']},
            {test:/\.less$/,use:['style-loader','css-loader','less-loader']},
            {test:/\.scss$/,use:['style-loader','css-loader','sass-loader']},
            {test:/\.(jpg|png|gif|bmp|jpeg)$/,use:'url-loader'},
            {test:/\.js$/,use:'babel-loader',exclude:/node_modules/},
            {test:/\.vue$/,use:'vue-loader'}//新增
        ]
    }

}

4)创建.vue文件

<!--login.vue-->
<template>
    <h1>sdsdsd</h1>
</template> 
<script></script>
<style scoped>
/*私有样式*/
h1{
    color:red;
}
</style>

5)main.js文件中导入

import login from './login.vue'
new Vue({
    el:'#app',//index.html中定义的容器
    render:c=>c(login)
})

6)路由

(1)安装

npm i vue-router -s

(2)导入

import Vue from 'vue'
import VueRouter from 'vue-router'//新增
Vue.use(VueRouter)//新增

(3)定义vue模板

vscode上安装vetur插件

<template>
<!--app.vue--> 
<!--根模板--> 
    <div>
        <router-link to='/accout'>accout</router-link>
        <router-link to='/productlist'>productlist</router-link>
        <router-view></router-view>
    </div>
</template> 
<script></script>
<style scoped>
</style>
<template> 
<!--accout.vue--> 
    <div>
        this is accout
    </div>
</template> 
<script></script>
<style scoped>
</style>
<template> 
<!--productlsit.vue--> 
    <div>
        this is productlist
    </div>
</template> 
<script></script>
<style scoped>
</style>

(4)导入模板、定义路由、创建app

//导入vue模板
import app from './app.vue'
import accout from './accout.vue'
import productlist from './productlist.vue'

//定义路由
var router=new VueRouter({
    routes:[
        {path:'/accout',component:accout},
        {path:'/productlist',component:productlist}
    ]
})

//创建app并注册路由
new Vue({
    el:'#app',
    render:c=>c(app),
    router
})

子路由和这里类似,需要在对应vue模板定义router-view、router-link标签,router-link的to属性上按照二级路由的方式进行定义


小功能案例

回到顶部功能实现

1)定义按钮

<v-btn color="primary" v-show="backTopShow" fab small dark fixed right bottom @click="$vuetify.goTo(0, 'duration')">
    <v-icon>mdi-chevron-up</v-icon>
</v-btn>

需要用fixed使其固定在窗口某一位置,点击后跳转到顶部

2)定义监听功能

export default {
    name: 'App',
    data: () => ({
      backTopShow: true, //回到顶部按钮是否显示
    }),
    methods: {
      handleScroll() {
        let scrollTop = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop
        if (scrollTop > 100) {//滚动距离大于100显示,否则隐藏
          this.backTopShow = true
        }else{
          this.backTopShow = false
        }
      }
    },
    mounted() {
      window.addEventListener('scroll', this.handleScroll) // 监听滚动事件,然后用handleScroll这个方法进行相应的处理
    }
  };

npm安装依赖报错

原因:

在安装saas时报错,导致后面的依赖无法安装

解决办法:

在项目内添加一个 .npmrc 文件

phantomjs_cdnurl=http://cnpmjs.org/downloads
sass_binary_site=https://npm.taobao.org/mirrors/node-sass/
registry=https://registry.npm.taobao.org

此方法不一定可以解决,可以摈弃用npm,改用yarn

Yarn安装

npm i -g yarn

安装依赖

yarn

切换国内源

yarn config set registry https://registry.npm.taobao.org --global
yarn config set disturl https://npm.taobao.org/dist --global

启动

yarn dev

打包

yarn build
posted @ 2024-03-22 16:58  SylvesterZhang  阅读(38)  评论(0)    收藏  举报