精华内容
下载资源
问答
  • vue cli3打包报错

    2021-09-28 10:27:52
    error 'scope' is defined but never used vue/no-unused-vars 报错是element-ui的scope,定义了但没用过 报错1解决: 由于我不喜欢vscode的自动格式化效果,一屏放不下几行代码,所以我不打算格式化我的代码来...

    报错1:

     272:1  error  Irregular whitespace not allowed  no-irregular-whitespace
    
    

    报错是没有用规范的写法,有多余的空格

    报错2:

    error  'scope' is defined but never used  vue/no-unused-vars
    
    

    报错是element-ui的scope,定义了但没用过

    报错1解决:
    由于我不喜欢vscode的自动格式化效果,一屏放不下几行代码,所以我不打算格式化我的代码来解决这个问题,最后是屏蔽乐eslint代码的格式报错:

    1. 进入node_modules\eslint-config-standard
    2. 打开eslintrc.json
    3. 在rules里将 “no-irregular-whitespace”: “error” 改为"no-irregular-whitespace": “off”

    报错2解决
    slot-scope是elment-ui自定义的指令,有时候需要自定义但是并不需要使用scope这个参数,在代码中会报红,但是项目运行不影响,打包报了错。

    原写法:

    <template slot="header" slot-scope="scope">
    	<div class="tec_forcast_title">
    	...
    	</div>
    <template>
    

    解决报错的写法:

    <template slot="header" slot-scope="{}">
    	<div class="tec_forcast_title">
    	...
    	</div>
    <template>
    
    展开全文
  • 自定义指令中生命周期分为五个阶段,分别是 bind, // DOM渲染前 inserted, // DOM渲染后 update, // DOM更新前 componentUpdate, // DOM更新完成后 unbind // 指令销毁 1.新建一个文件夹directives,里面新建一个...

    需要知道的知识:
    自定义指令中生命周期分为五个阶段,分别是
    bind, // DOM渲染前
    inserted, // DOM渲染后
    update, // DOM更新时
    componentUpdate, // DOM更新完成后
    unbind // 指令销毁
    1.新建一个文件夹directives,里面新建一个index.js文件
    在这里插入图片描述
    2.index.js文件中如下配置
    示例一个img图片加载异常的自定义处理指令

    export default {
    imgError:{
    insert(dom,obj,vnode){
    if(dom.src){  // 对标签里的src属性做判断,如果存在,就优先使用原本的src路径,如果报错了,就用设置的传入参数作为替换
    dom.src=dom.src || obj.value
    dom.onerror = function(){
    dom.src = dom.value
    }
    }},
    componentUpdated(dom,obj,vnode){ //当更新之后,还是优先原本达到src路径,上面的onerror是全局错误监听事件
    dom.src = dom.src || obj.value
    },
    unbind(dom,obj,vnode){  // 清除监听事件
    dom.onerror = null
    }
    }
    }
    

    3.在main.js中导入,并注册
    import directives from ‘@/directives’
    Object.keys(directives).forEach(item=>{ //Object.keys(),对对象属性进行遍历
    Vue.directive(item,directives[item])
    })

    展开全文
  • 自定义指令 除了核心功能默认内置的指令 (v-model 和 v-show),Vue 也允许注册自定义指令。 // 注册一个全局自定义指令 `v-focus` Vue.directive('focus', { bind:function(el){}, // 当被绑定的元素插入到 DOM ...

    自定义指令

    • 除了核心功能默认内置的指令 (v-model 和 v-show),Vue 也允许注册自定义指令。
    // 注册一个全局自定义指令 `v-focus`
    Vue.directive('focus', {
    	bind:function(el){},
      // 当被绑定的元素插入到 DOM 中时
      inserted: function (el) {
        // 聚焦元素
        el.focus()
      },
      updated:function(el){}
    })
    

    钩子函数bind,inserted,updated

    bind:只调用一次,指令第一次绑定到元素时调用,在这里可以进行一次性化设置

    inserted:被绑定元素插入父节点时调用

    update:所在组件VNode更新时调用,但是可能发生在其子VNode更新之前。

    • 钩子函数参数
      • el:指令所绑定的元素,可以用来直接操作 DOM。
      • 在这里插入图片描述

    私有指令(局部指令)

    ...
    <div id='#app'>
       <div v-color>hello word</div>
    </div>
    ...
    <script>
    var vm=new Vue({
    	el:'#app',
    	data:{},
    	methdos:{},
    	directives:{
    		color:{
    			bind:function(el){
    			el.style.color='red'
    			},
    			inserted:function(el){},
    			update:function(el){}
    		}
    	}
    })
    </script>
    

    函数简写

    在很多时候,想在bind和update是触发相同行为,而不关系其他的钩子

    Vue.directive('color-swatch',function(el,binding){
    	el.style.backgroundColor=binding.value
    })
    
    <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>指令使用钩子函数的第二个binding参数</title>
        <script src="../vue.min.js"></script>
        <script src="https://s3.pstatp.com/cdn/expire-1-M/jquery/3.3.1/jquery.min.js"></script>
        <script src="../bootstrap-3.3.7-dist/js/bootstrap.min.js"></script>
        <link rel="stylesheet" href="../bootstrap-3.3.7-dist/css/bootstrap.min.css">
        <style>
            #id {
                width: 200px;
            }
        </style>
    </head>
    
    <body>
        <div id="app">
    
            <div class="panel panel-primary">
                <div class="panel-heading">
                    <h3 class="panel-title">城市列表</h3>
                </div>
                <div class="panel-body form-inline">
                    id:<input type="text" name="" id="id" class="form-control" value="" required="required" pattern="" title="" v-model="id"> name:
                    <input type="text" name="" id="name" class="form-control" value="" required="required" pattern="" title="" v-model="name">
    
                    <input type="button" value="添加" @click="add">
                    <label for="">查询</label>
    
                    <input type="text" name="" id="search" class="form-control" value="" required="required" pattern="" title="">
                </div>
            </div>
    
    
            <table class="table table-striped table-hover table-bordered">
                <thead>
                    <tr>
                        <th>id</th>
                        <th>name</th>
                        <th>时间</th>
                        <th>操作</th>
                    </tr>
                </thead>
                <tbody>
                    <tr v-for="list in listsdata">
                        <td v-fontweight="1000">{{list.id}}</td>
                        <td>{{list.name}}</td>
                        <td>{{list.ctime}}</td>
                        <td><a href="#" @click="delt(list.id)">删除</a></td>
                    </tr>
                </tbody>
            </table>
            <!-- 测试命令指令钩子函数的第二个参数 -->
            <label for="" v-color="'red'">{{new Date()}}</label>
    
    
        </div>
    
    
    </body>
    <script>
        // 测试命令指令钩子函数第二个参数,钩子函数binding,inserted,updated.分别的参数
        Vue.directive('color', {
            bind: function(el, binding) {
                el.style.color = binding.value
            }
        })
        var vm = new Vue({
            el: '#app',
            data: {
                id: '',
                name: '',
                listsdata: [{
                    id: 1,
                    name: '北京',
                    ctime: new Date()
                }, {
                    id: 2,
                    name: '上海',
                    ctime: new Date()
                }, {
                    id: 3,
                    name: '广州',
                    ctime: new Date()
                }]
            },
    
            methods: {
                add() {
                    var city = {
                        id: this.id,
                        name: this.name,
                        ctime: new Date()
                    }
                    this.listsdata.push(city)
    
                },
                delt(id) {
                    this.listsdata.forEach((item, i) => {
                        if (item.id == id) {
                            this.listsdata.splice(i, 1)
                        }
                    })
    
                }
            },
    
            directives: {
                fontweight: {
                    bind: function(el, binding) {
                        el.style.fontWeight = binding.value
                    }
                }
            }
        })
    </script>
    
    </html>
    

    Vue实例的生命周期

    • 什么是生命走起,从Vue实例创建、运行到销毁期间,总是伴随着各种各样的时间,这些事件,统称为生命周期。
    • 生命周期钩子是生命周期事件的别名而已
    • 主要的生命周期函数分类:
      1. 创建期间的生命周期函数:
        • beforeCreate:实例刚在内存中被创建出来,此时,还没有初始化好data和methods属性
        • created:实例已经在内存中创建OK,此时data和methods已经创建ok,此时还没有开始编译模板
        • beforeMount:此时已经完成了模板的编译,但是还没有挂载到页面中
        • Mount:此时已经将编译好的模板,挂载到了页面指定的容器中显示
      2. 运行期间的生命周期函数:
        • beforeUpdate:状态更新之前执行此函数,此时data中的状态值是最新的,但是界面上显示的数据还是旧的,因为此时还没有开始重新渲染DOM节点
        • updated:实例更新完毕之后调用此函数,此时data中的状态值和界面上显示的数据都已经完成了更新,界面已经被重新渲染好了
      3. 销毁期间的生命周期函数:
        • beforeDestroy:实例销毁之前调用,在这一步,实例仍然完全可用
        • destroyed: Vue实例销毁后调用,调用后,Vue实例都会被消除

    V-resource包完成get,post,JSONP请求

    详见代码
    app.js

    <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>v-resourse中的get,post以及jsonp请求</title>
        <script src="../vue.min.js"></script>
        <script src="../vue-resource-1.3.4.js"></script>
    </head>
    
    <body>
        <div id="app">
            <input type="button" value="发送get请求" @click="reGet">
            <input type="button" value="发送get请求" @click="rePost">
            <input type="button" value="发送JSONP请求" @click="reJSONP">
        </div>
    
    </body>
    <script>
        var vm = new Vue({
            el: '#app',
            data: {},
            methods: {
                reGet() {
                    this.$http.get('http://www.liulongbin.top:3005/api/getlunbo').then(function(response) {
                        console.log(response)
                    })
                },
                rePost() {
                    this.$http.post('http://www.liulongbin.top:3005/api/post', { name: 'tom'}, {emulateJSON: true}).then(result => {
                        console.log(result)
                    })
                },
                reJSONP(){
                    this.$http.jsonp('http://www.liulongbin.top:3005/api/jsonp').then(result=>{
                        console.log(result)
                    })
                }
    
            }
        })
    </script>
    
    </html>
    

    语法&API
    可以使用全局对象Vue.http或者一个Vue实例的内部使用this.$http来发起HTTP请求

    //全局Vue对象使用http
    Vue.http.get(url,[options]).then(successCallback,errorCallback)
    Vue.http.post(url,[body],[options]).then(successCallback,errorCallback)
    Vue.http.jsonp(url,[options]).then(successCallback,errorCallback)
    //在一个Vue实例内使$http
    this.$http.get(url,[options]).then(successCallback,errorCallback)
    this.$http.post(url,[body],[options]).then(successCallback,errorCallback)
    this.$http.jsonp(url,[options]).then(successCallback,errorCallback)
    

    ** 注意:** post发送数据到后端,需要第三个参数{emulateJSON:true}。作用,如果web服务器无法处理编码为application/json的请求,可以启用emulateJSON选项
    在这里插入图片描述

    手动创建node.js服务器,用于测试JSONP

    服务器端node.js

    //导入http内置模块
    const http=require('http')
    //这个核心模块,能够帮我们解析url地址,从而拿到pathname 、query
    const urlModel=require('url')
    
    
    // 创建一个http服务
    const server=http.createServer()
    
    //监听http服务器的request请求
    server.on('request',function(req,res){
    //这里写自己的代码
    // const url= req.url
    
    const {pathname:url,query}=urlModel.parse(req.url,true)
    
    if(url==='/getScript'){
        //回调的数据
        var data={
            name:'tom',
            age:23,
        }
        //拼接一个合法的js脚本,这里拼接的是一个方法的调用
        // var scriptStr='show()'
        var scriptStr=`${query.callback}(${JSON.stringify(data)})`
        //res.end 发送给客户端,客户端去把这个字符串,当做js代码去解析执行
        res.end(scriptStr)
    }else{
        res.end('404')
    }
    
    
    
    })
    
    //指定端口号并启动服务器监听
    server.listen(3000,function(){
        console.log('server listen at http://127.0.0.1:3000')
    })
    

    开启服务·的命令 node app.js
    客户端js

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>结合node手写JSONP服务器剖析JSONP</title>
    </head>
    <body>
        
    </body>
    <script>
        // function show(){
        //     console.log("ok")
        // }
        function showinfo(data){
            console.log(data)
        }
    </script>
    
    <script src="http://127.0.0.1:3000/getScript?callback=showinfo"></script>
    </html>
    

    第三天

    • v-resourse请求服务器端完成商品列表的操作
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>v-resource完成商品列表的操作</title>
        <script src="../vue.min.js"></script>
        <script src="../vue-resource-1.3.4.js"></script>
        <script src="https://s3.pstatp.com/cdn/expire-1-M/jquery/3.3.1/jquery.min.js"></script>
        <script src="../bootstrap-3.3.7-dist/js/bootstrap.min.js"></script>
        <link rel="stylesheet" href="../bootstrap-3.3.7-dist/css/bootstrap.min.css">
    </head>
    <body>
        <div id="app">
    
            
            <div class="panel panel-primary">
                  <div class="panel-heading">
                        <h3 class="panel-title">商品列表</h3>
                  </div>
                  <div class="panel-body form-inline">
                        <label >
                            name:
                            <input type="text" name="" id="input" class="form-control" value="" required="required" pattern="" title="" v-model="name">
                        </label>
                        <input type="button" value="添加" @click="add">
                  </div>
            </div>
            
    
            <table class="table table-bordered table-hover table-striped">
                <thead>
                    <tr>
                        <th>id</th>
                        <th>name</th>
                        <th>时间</th>
                        <th>操作</th>
                    </tr>
                </thead>
                <tbody>
                    <tr v-for="list in listdata" :key='list.id'>
                        <td>{{list.id}}</td>
                        <td>{{list.name}}</td>
                        <td>{{list.ctime}}</td>
                        <td><a href="#" @click="del(list.id)">删除</a></td>
                    </tr>
                </tbody>
            </table>
            
        </div>
          
    </body>
    <script>
        //配置全局url地址请求的数据接口和根域名,根路径
        Vue.http.options.root="http://api.cms.liulongbin.top/"
        //全局启用emulateJSON选项
        Vue.http.options.emulateJSON=true
        var vm=new Vue({
            el:'#app',
            data:{
                name:'',
                listdata:[
                    {id:1,name:'tom',ctime:new Date()},
                    {id:2,name:'jerry',ctime:new Date()}
                ]
            },
            created(){
                this.getAllLists()
            },
            methods:{
                getAllLists(){
                    // 通过全局配置请求数据接口,根域名,则每次单独发起http请求1的时候,请求的url路径,应该以相对路径开头,前面不能带/,否则不会启用根路径做拼接
                    this.$http.get('api/getprodlist').then(result=>{
                        var results=result.body
                        if(results.status==0){
                            this.listdata=results.message
                        }else{
                            alert("列表不存在")
                        }
                    })
                },
                add(){
                    // 注意这里传递的数据是以对象传递的
                    this.$http.post('api/addproduct',{name:this.name},{emulateJSON:true}).then(result=>{
                        var results=result.body
                        if(results.status==0){
                            this.getAllLists()
                            this.name=''
                        }
                    })
                },
                del(produce_id){
                    this.$http.get('api/delproduct/'+String(produce_id)).then(result=>{
                        var results=result.body
                        if (results.status==0){
                            this.getAllLists()
                        }
                    })
                }
            }
        })
    </script>
    </html>
    

    Vue动画

    在这里插入图片描述

    动画 自定义v-前缀

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>动画自定义v-前缀</title>
        <script src="../vue.min.js"></script>
        <style>
            .my-enter,.my-leave-to{
                opacity: 0;
                transform: translateY(100px);
            }
            .my-enter-active,.my-leave-active{
                transition: ease 2s all;
            }
        </style>
    </head>
    <body>
        <div id="app">
            <input type="button" value="动画" @click='flag=!flag'>
            <transition name='my'>
                <h3 v-if='flag'>这是一个动画</h3>
            </transition>
        </div>
    </body>
    <script>
        var vm=new Vue({
            el:'#app',
            data:{
                flag:false
            },
    
        })
    </script>
    </html>
    

    使用第三方animate.css实现动画

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>动画自定义v-前缀</title>
        <script src="../vue.min.js"></script>
        <link rel="stylesheet" href="../animate.css">
        <style>
            .my-enter,.my-leave-to{
                opacity: 0;
                transform: translateY(100px);
            }
            .my-enter-active,.my-leave-active{
                transition: ease 2s all;
            }
        </style>
    </head>
    <body>
        <div id="app">
            <input type="button" value="动画" @click='flag=!flag'>
            <!-- <transition name='my'>
                <h3 v-if='flag'>这是一个动画</h3>
            </transition> -->
    
            <!-- 使用animate.css实现动画效果 -->
            <transition enter-active-class="animated bounceIn" leave-active-class="animated bounceOut" >
                <h2 v-if='flag'>这里使用animate.css来实现一部分动画效果</h2>
            </transition>
        </div>
    </body>
    <script>
        var vm=new Vue({
            el:'#app',
            data:{
                flag:false
            },
    
        })
    </script>
    </html>
    

    利用钩子函数实现动画

    样式:

    <transition
      v-on:before-enter="beforeEnter"
      v-on:enter="enter"
      v-on:after-enter="afterEnter"
      v-on:enter-cancelled="enterCancelled"
    
      v-on:before-leave="beforeLeave"
      v-on:leave="leave"
      v-on:after-leave="afterLeave"
      v-on:leave-cancelled="leaveCancelled"
    >
      <!-- ... -->
    </transition>
    // ...
    methods: {
      // --------
      // 进入中
      // --------
    
      beforeEnter: function (el) {
        // ...
      },
      // 当与 CSS 结合使用时
      // 回调函数 done 是可选的
      enter: function (el, done) {
        // ...
        done()
      },
      afterEnter: function (el) {
        // ...
      },
      enterCancelled: function (el) {
        // ...
      },
    
      // --------
      // 离开时
      // --------
    
      beforeLeave: function (el) {
        // ...
      },
      // 当与 CSS 结合使用时
      // 回调函数 done 是可选的
      leave: function (el, done) {
        // ...
        done()
      },
      afterLeave: function (el) {
        // ...
      },
      // leaveCancelled 只用于 v-show 中
      leaveCancelled: function (el) {
        // ...
      }
    }
    

    注意:当只用js过渡的时候,在enter和leave中必须使用done进行回调,否则,他们将被同步调用,过渡会立即完成。
    动画钩子函数的第一个参数:el表示要执行动画的那个DOM元素,是个原生的js dom对象

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>使用钩子函数实现小球的半场动画</title>
        <script src="../vue.min.js"></script>
        <style>
            .ball{
                height: 15px;
                width: 15px;
                background-color: brown;
                border-radius: 50%;
            }
            
        </style>
    </head>
    <body>
        <div id="app">
            <button @click='flag=!flag'>小球移动</button>
            <transition @before-enter='beforeEnter' @enter='Enter' @after-enter='afterEnter'>
                <div class="ball" v-if="flag"></div>
            </transition>
            
        </div>
    </body>
    <script>
        var vm=new Vue({
            el:'#app',
            data:{
                flag:false
            },
            methods:{
                beforeEnter(el){
                    // befroe-enter表示动画入场之前,此时,动画尚未开始,可以在beforeEnter中设置元素开始动画之前的起始样式
                    el.style.transform="translate(0,0)"
                },
                Enter(el,done){
                    // 这句话,没有实际的作用,但是,如果不写,出不来动画效果;
                    // 可以认为 el.offsetWidth 会强制动画刷新
                    el.offsetWidth    
                    el.style.transform="translate(300px,100px)"
                    el.style.transition="all 1s ease"
                    done()
                },
                afterEnter(){
                    this.flag=!this.flag
                }
            }
        })
    </script>
    </html>
    

    使用transition-group元素实现列表的动画

    列表过渡:

    • 使用 组件。不同于,它会一个真实元呈现,默认为一个,可以通过tag更换为其他元素
    • 内部元素总是需要提供唯一的key值
    <!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>
      <script src="./lib/vue-2.4.0.js"></script>
      <style>
        li {
          border: 1px dashed #999;
          margin: 5px;
          line-height: 35px;
          padding-left: 5px;
          font-size: 12px;
          width: 100%;
        }
    
        li:hover {
          background-color: hotpink;
          transition: all 0.8s ease;
        }
    
    
    
        .v-enter,
        .v-leave-to {
          opacity: 0;
          transform: translateY(80px);
        }
    
        .v-enter-active,
        .v-leave-active {
          transition: all 0.6s ease;
        }
    
        /* 下面的 .v-move 和 .v-leave-active 配合使用,能够实现列表后续的元素,渐渐地漂上来的效果 */
        .v-move {
          transition: all 0.6s ease;
        }
        .v-leave-active{
          position: absolute;
        }
      </style>
    </head>
    
    <body>
      <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>
    
        <!-- <ul> -->
          <!-- 在实现列表过渡的时候,如果需要过渡的元素,是通过 v-for 循环渲染出来的,不能使用 transition 包裹,需要使用 transitionGroup -->
          <!-- 如果要为 v-for 循环创建的元素设置动画,必须为每一个 元素 设置 :key 属性 -->
          <!-- 给 ransition-group 添加 appear 属性,实现页面刚展示出来时候,入场时候的效果 -->
          <!-- 通过 为 transition-group 元素,设置 tag 属性,指定 transition-group 渲染为指定的元素,如果不指定 tag 属性,默认,渲染为 span 标签 -->
          <transition-group appear tag="ul">
            <li v-for="(item, i) in list" :key="item.id" @click="del(i)">
              {{item.id}} --- {{item.name}}
            </li>
          </transition-group>
        <!-- </ul> -->
    
      </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: '魏忠贤' }
            ]
          },
          methods: {
            add() {
              this.list.push({ id: this.id, name: this.name })
              this.id = this.name = ''
            },
            del(i) {
              this.list.splice(i, 1)
            }
          }
        });
      </script>
    </body>
    
    </html>
    

    Vue组件 (重点)

    组件的出现,就是为了拆分Vue实例的代码量,能够让我们以不同的组件,来划分不同的功能模块,将来我们需要什么样的功能,就去调用相应的逐渐即可。
    组件化和模块化的不同:

    • 模块化:是从到吗的逻辑角度进行的划分,方便代码的分层开发,保证每个功能模块的职能单一;
    • 组件化:是从UI界面的角度进行划分的,前端的组件化,方便ui组件的重用
      全局组件定义的三种方式以及定义私有组件:
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>定义组件的三种方式</title>
        <script src="../vue.min.js"></script>
    </head>
    <body>
        <div id="app">
            <login></login>
            <login2></login2>
            <login3></login3>
            <login4></login4>
        </div>
        
        <template id="log">
            <h3>这是第三种方式</h3>
        </template>
    
        <template id="log4">
            <h3>这是一个私有的组件</h3>
        </template>
    </body>
    <!-- 定义全局组件的三种方式 -->
    <script>
        // <!-- 第一种 -->
        var login=Vue.extend({
            template:'<h1>这是第一种方式</h1>'
        })
        Vue.component('login',login)
    
        // 第二种
        Vue.component('login2',Vue.extend({
            template:'<h2>这是第二种</h2>'
        }))
    
        //第三种方式
        Vue.component('login3',{
            template:'#log'
        })
    
        var vm=new Vue({
        el:'#app',
        data:{},
        methods:{},
        // 这是私有的组件
        components:{
            login4:{
                template:'#log4'
            }
        }
        })
    </script>
    
    </html>
    

    组件中data,以及为什么data必须是一个function函数

    组件是可复用的vue1实例,一个组件被创建好之后,就可能被用在各个地方,而组件不管被复用了多少次,组件中的data数据都应该是相互隔离,互不影响的,基于这个理念,组件每复用一次,data数据就应该被复制一次,之后,当某一处复用的地方组件内data数据被改变时,其他复用地方组件的data数据不受影响

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>组件中的data方法</title>
        <script src="../vue.min.js"></script>
    </head>
    <body>
        <div id="app">
            <login></login>
        </div>
        <template id="log">
            <div>
                <input type="button" value="点击" @click="add">
                <h3>这是一个组件用来测试data---{{count}}</h3>
            </div>
        </template>
    </body>
    <script>
        Vue.component('login',{
            template:'#log',
            //1.组件可以有组件的data数据
            //2.组件的data和实例中的data不一样,实例中的data可以为一个对象,但是组件中的data必须是一个方法
            //3.组件中的data除了必须为一个方法之外,这个方法内部,还必须返回一个对象才行
            data:function(){
                return {count:1}
            },
            methods:{
                add(){
                    this.count++
                }
            }
        })
        var vm=new Vue({
            el:'#app',
            data:{}
        })
    </script>
    </html>
    

    注意:为什么要使用function来返回对象,是为了组件的重复使用。

    组件的切换(例如登录注册)

    1. 使用v-if和v-else进行切换
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>v-if和v-else控制组件的切换</title>
        <script src="../vue.min.js"></script>
    </head>
    <body>
        <div id="app">
            <a href="" @click.prevent="flag=true">登录</a>
            <a href="" @click.prevent="flag=false">注册</a>
            <login v-if="flag"></login>
            <register v-else="flag"></register>
        </div>
    
        <!-- 组件 -->
        <template id="log">
            <h3>这是登录组件</h3>
        </template>
    
        <template id="reg">
            <h3>这是注册组件</h3>
        </template>
    
    </body>
    <!-- 1.定义组件 component
    2.显示组件 template
    3.v-if控制组件的显示 -->
    <script>
        // 定义组件
        Vue.component('login',{
            template:'#log'
        })
    
        Vue.component('register',{
            template:'#reg'
        })
    
    
       var vm=new Vue({
           el:'#app',
           data:{
               flag:true
           },
           methods:{
               
           }
       })
    </script>
    </html>
    
    1. 使用Vue提供的component元素实现组件切换
    • Vue提供了component,来展示对应名称的组件,:is属性可以用来指定要展示的组件的名称
    • 注意:组件的名称要用单引号包裹起来如下例子
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>父组件向子组件传值</title>
        <script src="../vue.min.js"></script>
    </head>
    <body>
        <div id="app">
            <!-- 这里的:is里面要件单引号,否则的话会被解析成变量 -->
           <component :is="'temp1'"></component>
        </div>
        <template id="tem1">
        	<h1>这是一个组件</h1>
        </template>
    </body>
    <script>
        var vm =new Vue({
            el:'#app',
            data:{
                msg:"这是父组件的值"
            },
            methods:{},
            components:{
                temp1:{
                    template:'#tem1'
                },
            }
          
        })
    </script>
    </html>
    
    • 组件切换动画:组件过渡简单很多,不需要使用key。只需要使用动态组件:
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>v-if和v-else控制组件的切换</title>
        <script src="../vue.min.js"></script>
        <style>
            .v-enter,.v-leave-to{
                opacity: 0;
                transform: translateX(100px);
            }
            .v-enter-active,.v-leave-active{
                transition: ease all 0.3s;
            }
        </style>
    </head>
    <body>
        <div id="app">
            <a href="" @click.prevent="name='login'">登录</a>
            <a href="" @click.prevent="name='register'">注册</a>
            <!-- 添加切换动画 -->
            <!-- 通过mode属性来设置组件的切换模式 -->
            <transition mode='out-in'>
                <component :is="name"></component>
            </transition>
           
        </div>
    
        <!-- 组件 -->
        <template id="log">
            <h3>这是登录组件</h3>
        </template>
    
        <template id="reg">
            <h3>这是注册组件</h3>
        </template>
    
    </body>
    
    <script>
        // 定义组件
        Vue.component('login',{
            template:'#log'
        })
    
        Vue.component('register',{
            template:'#reg'
        })
    
       var vm=new Vue({
           el:'#app',
           data:{
               name:'login'
           },
           methods:{
               
           }
       })
    </script>
    </html>
    

    - 组件传值 –父组件向子组件传值和data与props的区别

    父传子传值流程:

    1. 父组件在data定义数据
    2. 子组件标签绑定父组件数据
    3. 子组件定义props数组,定义标签绑定的属性
    4. 子组件使用这个属性
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>父组件向子组件传值</title>
        <script src="../vue.min.js"></script>
    </head>
    <body>
        <div id="app">
            <!-- 这里的:is里面要件单引号,否则的话会被解析成变量 -->
           <component :is="'temp1'" :parentmsg="msg"></component>
        </div>
        <template id="tem1">
            <h1 @click="change">我是{{childmsg}},将要调用父组件--->{{parentmsg}}</h1>
        </template>
    </body>
    <script>
        var vm =new Vue({
            el:'#app',
            data:{
                msg:"这是父组件的值"
            },
            methods:{},
            components:{
                temp1:{
                    //注意:组件中的data是一个方法,返回一个对象
                    data(){
                        return {childmsg:'子组件'}
                    },
                    template:'#tem1',
                    //注意:组件中所有props中的数据,都是父组件传递给子组件的。props中的数据都是只读的,建议不要修改
                    props:['parentmsg'] , //把父组件传递过来的parentmsg属性,现在props数组中定义以下,这样才能使用这个值
                    methods:{
                        change(){
                            this.childmsg="子组件被修改了"
                        }
                    }
    
                },
            }
          
        })
    </script>
    </html>
    

    注意: 1. props中所有的数据,都是通过父组件传递给子组件的。子组件想要自己数据,则可以使用data。2. 子组件中的data是个函数。返回一个对象。

    - 组件传值–子组件通过事件调用向父组件传值$emit

    原理:父组件将方法的引用,传递到子组件内部,子组件在内部调用父组件传递过来的方法,同时把要发送给父组件的数据,在调用方法的时候当做参数传递进去
    子组件内部通过"this.$emit"(‘方法名’,要传递的数据)方式,来调用父组件中的方法,同时把数据传递给父组件使用。

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>子组件向父组件传值</title>
        <script src="../vue.min.js"></script>
    </head>
    <body>
        <div id="app">
            <template1 @func="show"></template1>
        </div>
    
        <template id="temp1">
            <div>
                <h1>我是子组件,将要通过调用父组件的函数进行传值</h1>
                <input type="button" value="点击我调用父组件方法show并传值" @click="task">
            </div>
        </template>
        
    </body>
    <script>
        var vm=new Vue({
            el:'#app',
            data:{},
            methods:{
                show(arg1){
                    console.log(arg1)
                }
            },
            // 定义组件
            components:{
                template1:{
                    template:'#temp1',
                    methods:{
                        task(){
                            this.$emit('func',"这是子组件传递的值")
                        }
                    }
                },
                
            }
        
        })
    </script>
    </html>
    

    注意:
    在这里插入图片描述
    例子:组件实现评论功能

    <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>组件实现发表评论的功能</title>
        <script src="../vue.min.js"></script>
        <script src="../jquery-3.4.1.min.js"></script>
        <script src="../bootstrap-3.3.7-dist/js/bootstrap.min.js"></script>
        <link rel="stylesheet" href="../bootstrap-3.3.7-dist/css/bootstrap.min.css">
    </head>
    <!-- 
        分析:发表评论的业务逻辑 
        1.评论数据存到localStorage中
        2.获取最新的评论数据对象
        3.将得到的对象保存到localStorage中
            3.1 localStorage只支持字符串数据,线调用JSON.stringify
            3.2 开始的时候要先得到以前存在localStorage中的数据 JSON.parse转为数组对象
            然后把最新数据unshift放在数组首位存到localStorage
            3.3如果获取到的localStorage中的字符串为空不存在,则可以返回'[]',让JSON.parse去解析
        4.组件添加了评论之后,调用父组件的方法显示更新后的localStorage
    -->
    <body>
        <div id="app">
            <!-- //评论编写的部分做成组件 -->
            <template1 @func="getStorage"></template1>
            <ul class="list-group">
                <li class="list-group-item" v-for="(item,i) in contentlists" :key="i">
                    <span class="badge">{{item.name}}</span> {{item.content}}
                </li>
            </ul>
        </div>
    
        <!-- 组件 -->
        <template id="temp1">
            <div>   
                
                <div class="panel panel-primary">
                      <div class="panel-heading">
                            <h3 class="panel-title">添加评论</h3>
                      </div>
                      <div class="panel-body">
                            <label class="form-inline">
                                name: 
                                <input type="text" name="" id="input" class="form-control" value="" required="required" pattern="" title="" v-model="name"> 
                            </label>
                            <br>
                            <label  class="form-inline">
                                content: 
                                <textarea name="" id="input" class="form-control" rows="3" required="required" v-model="contents"></textarea>
                            </label>
                            
                            <button type="button" class="btn btn-primary" @click="addContent">评论</button>
                            
                      </div>
                </div>
                
            </div>
        </template>
    
    </body>
    
    <script>
        var vm = new Vue({
            el: '#app',
            data: {
                contentlists: [
                    {name: '小明',content: "这里是小明"},
                    {name: '小红',content: "这里是小红"}, 
                    {name: '小张',content: "这里是小张"}, ]
            },
            created() {
                this.getStorage()
            },
            methods: {
                getStorage() {
                    this.contentlists = JSON.parse(localStorage.getItem('cmts') || "[]")
                }
            },
            components: {
                'template1': {
                    // 注意:组件中的data是一个函数,返回一个对象
                    data() {
                        return {name: '',contents: ''}
                    },
                    template: '#temp1',
                    methods: {
                        addContent() {
                            var con = {id: new Date(),name: this.name,content: this.contents}
                            var list = JSON.parse(localStorage.getItem('cmts') || '[]')
                            list.unshift(con)
                            localStorage.setItem('cmts', JSON.stringify(list))
                            this.name = this.contents = ''
                            this.$emit('func')
                        }
                    }
                }
            }
        })
    </script>
    
    </html>
    

    使用this.$refs来获取DOM元素和组件引用

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>使用this.$refs获取dom元素和组件引用</title>
        <script src="../vue.min.js"></script>
    </head>
    <body>
        <div id="app">
            <input type="button" value="获取dom元素和组件引用" @click="getTag">
            <template1 ref="ctag"></template1>
            <h3 ref="ptag">这是父组件</h3>
        </div>
    
        <template id="temp">
            <div>
                <h3>这是子组件</h3>
            </div>
        </template>
    </body>
    <script>
        Vue.component("template1",{
            template:'#temp',
            data(){
                return{name:'tom'}
            },
            methods:{
                add(){
                    console.log("这是子组件的add函数")
                }
            }
        });
        var vm=new Vue({
            el:'#app',
            data:{},
            methods:{
                getTag(){
                    console.log(this.$refs)
                    console.log(this.$refs.ptag.innerText) //输出: 这是父组件
                    console.log(this.$refs.ctag.name) //tom
                    this.$refs.ctag.add()   //这是子组件的add函数
                }
            },
        });
    </script>
    </html>
    

    例子:使用路由和组件实现经典的布局

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>使用命名组件来实现经典的布局</title>
        <script src="../vue.min.js"></script>
        <script src="../vue-router-3.0.1.js"></script>
        <style>
            *{
                margin: 0;
                padding: 0;
            }
            .he{
                width: 100%;
                height: 100px;
                border: solid 1px red;
            }
            .le{
                float: left;
                width: 20%;
                height: 400px;
                border: solid 1px blue;
            }
            .ri{
                float: left;
                width: 70%;
                height: 400px;
                border: solid 1px green;
            }
        </style>
    </head>
    <body>
        <div id="app">
            <router-view></router-view>
            <router-view name="left"></router-view>
            <router-view name="right"></router-view>
        </div>
    
        <template id="header">
            <h1 class="he">这是头部</h1>
        </template>
        <template id="left">
            <h1 class="le">这是左部</h1>
        </template>
        <template id="right"">
            <h1 class="ri">这是右部</h1>
        </template>
        
    </body>
    <script>
        var header={template:'#header'}
        var left={template:'#left'}
        var right={template:'#right'}
        // 当一个页面有多个路由的时候,在router-view标签中添加name,同时换成components
        var router=new VueRouter({
            routes:[
                {path:'/',components:{
                    default:header,
                    left:left,
                    right:right
                }}
            ]
        })
        var vm=new Vue({
            el:"#app",
            data:{},
            methdos:{},
            router:router
        });
    </script>
    </html>
    

    第五天

    前端路由

    • 什么是路由
    1. 后端路由 对于普通的网站,所有的超链接都是url地址,所有的url地址都对应服务器上对应的资源
    2. 前端路由对于单页面应用程序来说,主要通过url中的hash(#号)来实现不同页面之间的切换,同时,hash有一个特点:http请求中不包含hash相关的内容,单页面程序中的页面跳转主要用hash实现
    3. 在单页面应用程序中,这种通过hash改变来切换页面的方式,称为前端路由(区别于后端路由)

    vue-router实现前端路由。作用是:地址栏输什么,到什么页面,而且vue-router可以通过html5的history实现单页面应用,不刷新跳转,切地址,只是页面上组件的切换。另外还可以实现页面间传参等其他功能。

    使用流程:

    1. 创建一个路由对象,当导入vue-router包后,在window全局对象中,就有一个路由的构造函数,叫做vue-router。在new路由对象的时候,可以为构造函数,传递一个配置对象
    var routerobj=new VueRouter({
    		//router表示路由匹配规则的意思
    		routes:[
    		//每个路由规则都是一个对象,这个规则对象身上,有两个必须的属性
    		//属性1是path,表示监听哪个路由链接地址。属性2表示如果路由是前面匹配到的path,则展示component对应的那个组件
    		//注意:component属性必须是一个组件的模板对象,不能是组件的引用名称
    			{path:'地址',component::'组件'}
    		]
    })
    
    1. 将路由规则对象,注册到vm实例上,用来监听URL地址的变化,然后展示对应的组件
    var vm =new Vue({
    	el:'#app',
    	...
    	router:routerobj
    })
    
    1. 在页面添加router-view标签当做占位符,用来展示匹配到的组件
    <router-view></router-view>
    

    详细代码如下:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Vue-router前端路由的基本使用方法</title>
        <script src="../vue.min.js"></script>
        <script src="../vue-router-3.0.1.js"></script>
    </head>
    <body>
        <div id="app">
            <a href="#/login">登录</a>
            <a href="#/register">注册</a>
            <router-view></router-view>
        </div>
    
        <template id="reg"><h1>这是注册</h1></template>
    </body>
    <script>
        var login={template:'<h1>这是登录</h1>'}
        var register={template:'#reg'}
        // 定义路由
        var router=new VueRouter({
            routes:[
                {path:'/login',component:login},
                {path:'/register',component:register}
            ]
        })
    
        var vm=new Vue({
            el:'#app',
            data:{},
            methods:{},
            router:router
        })
    </script>
    </html>
    

    router-link的使用

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>测试router-link</title>
        <script src="../vue.min.js"></script>
        <script src="../vue-router-3.0.1.js"></script>
    </head>
    <body>
        <div id="app">
            <!-- 这里的router-link是vuerouter提供的标签 -->
            <router-link to="/login">登录</router-link>
            <router-link to="/register">注册</router-link>
    
            <router-view ></router-view>
        </div>
        <template id="log">
            <div><h1>这是登录</h1></div>
        </template>
        <template id="reg">
            <div>这是注册</div>
        </template>
    </body>
    <script>
        var login={template:'#log'}
        var register={template:'#reg'}
        var router=new VueRouter({
           routes:[
               {path:'/login',component:login},
               {path:'/register',component:register}
           ]
        })
        var vm=new Vue({
            el:'#app',
            data:{},
            methods:{},
            router:router
        })
    </script>
    </html>
    

    重定向

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>设置路由重定向</title>
        <script src="../vue.min.js"></script>
        <script src="../vue-router-3.0.1.js"></script>
    </head>
    <body>
        <div id="app">
            <a href="#/">首页</a>
            <a href="#/login">登录</a>
            <a href="#/register">注册</a>
            <router-view></router-view>
        </div>
        <template id="log">
            <div>
                这是登录界面
            </div>
        </template>
        <template id="reg">
            <div>
                这是注册界面
            </div>
        </template>
    </body>
    <script>
        var login={template:'#log'};
        var register={template:'#reg'};
    
        var router=new VueRouter({
            routes:[
                // {path:'/',component:login},
                // 重定向,这句话的意思是地址为'/'将转向到'/login'
                {path:'/',redirect:'/login'},
                {path:'/login',component:login},
                {path:'/register',component:register},
            ]
        });
    
        var vm=new Vue({
            el:'#app',
            data:{},
            methods:{},
            router:router
        });
    </script>
    </html>
    

    watch监听属性

    1. watch用来监听data中数据的变化
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>watch监听数据的变化</title>
        <script src="../vue.min.js"></script>
    </head>
    <body>
        <div id="app">
            <p>first: <input type="text" v-model="first"></p>
            <p>second: <input type="text" v-model="second"></p>
            <input type="text" v-model="last">
        </div>
    </body>
    <script>
        var vm=new Vue({
            el:'#app',
            data:{
                first:"",
                second:"",
                last:""
            },
            methods:{},
            watch:{
                // 参数oldval显示没有改变之前的值,newval指的是改变之后的值
                "first":function(newval,oldval){
                    this.last=this.first+this.second;
                    console.log(newval+"------"+oldval);
                },
                "second":function(){
                    this.last=this.first+this.second;
                }
            }
    
        });
    </script>
    </html>
    
    1. watch还可以用来监控路由地址的改变
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>使用watch来监听路由的改变</title>
        <script src="../vue.min.js"></script>
        <script src="../vue-router-3.0.1.js"></script>
        
    </head>
    <body>
        <div id="app">
            <a href="#/login">登录</a>
            <a href="#/register">注册</a>
           <router-view></router-view>
        </div>
        <template id="log">
            <h1>这是登录</h1>
        </template>
        <template id="reg">
            <h1>这是注册</h1>
        </template>
    
       
    </body>
    <script>
        var login={template:"#log"}
        var register={template:"#reg"}
        var router=new VueRouter({
            routes:[
                {path:'/login',component:login },
                {path:'/register',component:register}
                ]
        })
        var vm=new Vue({
            el:'#app',
            data:{},
            methods:{},
            router:router,
            watch:{
                "$route.path":function(newval,oldval){
                    // 这里显示路由的变化
                    console.log(newval+"---"+oldval);
                }
            }
        })
    </script>
    </html>
    
    
    
    

    computed 属性

    可以在computed中定义一些属性,这些属性是计算属性,计算属性本质就是一个方法,只不过在使用这些计算属性的时候,把他们的名称作为属性直接使用

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>使用computed计算属性</title>
        <script src="../vue.min.js"></script>
        <script src="../vue-router-3.0.1.js"></script>
        
    </head>
    <body>
       <div id="app">
           <p>first: <input type="text" v-model="first"></p>
           <p>second: <input type="text" v-model="second"></p>
           <p>last: <input type="text" v-model="last"></p>
       </div>
    
       
    </body>
    <script>
    var vm=new Vue({
        el:'#app',
        data:{
            first:'',
            second:''
        },
        methods:{
        },
        // 注意这个function内部所用到的任何data中的数据发生了变化,就会重新计算这个计算属性的值
        computed:{
            'last':function(){
                return this.first+this.second;
            }
        }
    });
    </script>
    </html>
    

    watch、computed和methods之间的对比

    1. computed属性的结果都会被缓存,除非依赖的响应式属性变化才会重新计算。
    2. methods方法表示一个具体的操作,主要书写业务逻辑
    3. watch主要监听某些特定数据的变化,从而进行某些具体的业务逻辑操作。

    第六天

    模块化相关规范

    传统开发模式的主要问题1,命名冲突2,,文件依赖
    通过模块化解决上述问题
    模块化是把单独的一个功能封装到一个模块(文件)中,模块之间相互隔离,但是可以通过特定的接口公开内部成员,也可以依赖别的模块。好处:方便代码重用,从而提升开发效率,并且方便后续的维护。

    *浏览器端模块化规范 *:AMD(主要代表Require.js)CMD(主要代表sea.js)

    服务器端模块化规范:CommonJS(1.模块分为单文件模块和包2.模块成员到处module.exports和 exports3.模块成员导入:require(‘模块表示符’))

    大一统模块规范–ES6模块化
    上面的这些模块标准,存在一定的差异性和局限性,并不是浏览器与服务器通用的模块化标准
    因此ES6在语言层面上规范,是浏览器端与服务器端通用的模块化开发规范。
    ES6模块规范中定义:

    • 每个js文件都是一个独立的模块
    • 导入模块成员使用import关键字·
    • 暴露模块成员用export关键字

    ES6中let和const

    • let是代码块内有效,var是全局范围有效
    {
      let a = 0;
      var b = 1;
    }
    a  // ReferenceError: a is not defined
    b  // 1
    
    • 不能重复生命
      let只能生命一次var可以声明多次
    let a = 1;
    let a = 2;
    var b = 3;
    var b = 4;
    a  // Identifier 'a' has already been declared
    b  // 4
    
    • 不存在变量提升
    console.log(a);  //ReferenceError: a is not defined
    let a = "apple";
     
    console.log(b);  //undefined
    var b = "banana";
    

    变量b用var声明存在变量提升,所以当脚本开始运行的时候,b已经存在了,但是还没有赋值,所以会输出undefined。变量a用let不存在变量提升,在声明变量a之前,a不存在,会报错

    • const声明一个只读变量,声明之后不允许改变,意味着,一旦声明必须初始化,否则会报错。

    模块的默认导入与导出
    前提:需要配置bable,参考通过 babel 体验 ES6 模块化
    1.默认导出语法:export default 默认导出成员 2.默认导入语法:import 接收名称 from 模块标识符
    在这里插入图片描述
    注意:只能用一次默认导出
    直接导入并执行模块代码
    只想单纯执行某个模块中的代码,并不需要得到模块中向外暴露成员,此时可以直接导入并执行模块代码

    在这里插入图片描述

    webpack(重点)

    • 在网页中会引用哪些常见的静态资源?
    • JS
    • .js .jsx .coffee .ts(TypeScript 类 C# 语言)
    • CSS
    • .css .less .sass .scss
    • Images
    • .jpg .png .gif .bmp .svg
    • 字体文件(Fonts)
    • .svg .ttf .eot .woff .woff2
    • 模板文件
    • .ejs .jade .vue【这是在webpack中定义组件的方式,推荐这么用】

    • 网页中引入静态资源多了会有什么问题?

    1. 网页加载速度慢,因为发起了很多二次请求;
    2. 要处理错综复杂的依赖关系
    • 如何解决上面两个问题?
      1.对js、css进行压缩,合并,精灵图,图片的base64编码
    1. 使用requireJs,也可以使用webpack解决包之间复杂的依赖关系
    • 什么是webpack?
      webpack是前端的一个项目构建工具,它是基于node.js开发出来的一个前端工具
      借助于webpack这个前端自动化构建工具,可以完美实现资源的合并、打包、压缩、混淆等诸多功能。

    webpack安装方式:

    1. 运行npm i webpack -g全局安装webpack,这样就能挂载全局使用webpack命令
    2. 在根目录中运行npm i webpack --save-dev安装到项目依赖中

    webpack使用例子(创建列表隔行变色项目)

    第一步:

    • . 新建项目空白目录 并运行npm init -y命令,初始化包管理配置文件package.json
    • . 新建src源代码目录
    • . 新建src—>index.html首页
    • 初始化首页基本结构
    • 运行npm install jquery -S命令 安装jquery
    • 通过模块化的形式(在src新建index.js),实例列表隔行变色效果
      创建后的文件夹如图所示,代码如图,并不会产生效果,需要进行下一步配置
      在这里插入图片描述

    在这里插入图片描述
    第二步:

    • 运行npm install webpack webpack-cli -D命令,安装webpack相关的包
    • 在项目中,创建名为webpack.config.js的webpack配置文件
    • 在webpack.config.js的配置文件中,初始化如下配置
      module.exports={ mode:"development" //mode用来指定构建模式 }
    • 在package.json配置文件中scripts节点下,新增dev脚本如下:
      "scripts":{ "dev":"webpack" //script节点下的脚本,可以通过npm run执行 }
    • 在命令行端运行 npm run dev
      在这里插入图片描述
      在这里插入图片描述
    展开全文
  • 1. 案例自定义组件结构 (自己创建项目目录) vue-plugin — |— build // 构建配置 |— webpack.base.conf.js // 基础构建配置 |— webpack.prod.conf.js // 打包(正式环境)的构建配置 ... |— config // ...

    1. 案例自定义组件结构 (自己创建项目目录)

    vue-plugin —
               |— build // 构建配置
                    |— webpack.base.conf.js  // 基础构建配置
                    |— webpack.prod.conf.js  // 打包(正式环境)的构建配置
                    ...
               |— config // 运行环境配置
               |— packages  // 组件内容
                    |— menu  // 具体的组件
                       |— menu.vue 
                       |— index.js  // 该组件的组测脚本
                    |— config  // 组件内容配置信息
               |— utils  // 组件的工具类
               |— css  // 组件引入的样式
                   |— variable.scss  // 样式变量
                   |— mixin.scss  // 样式混合
                   |— menu.scss  // menu组件样式
                   |— index.scss  样式总集
               |— src
                  |— ...
                  |— index.js  // 自定义组件的打包脚本(组件库的入口)
                  |— main.js  // 项目的本地运行和构建项目脚本
               |— package.json 
               |— README.md

     2. 自定义新建一个项目  (这里利用vue-cli2.0, 好修改配置信息)

    vue init vue-plugin
    // 然后安装依赖并运行
    
    npm install
    
    npm run dev


    3. 创建组件 以及每个组件的注册脚本(组件入口)

    // 创建menu组件
    menu.vue
    
    // 创建一个注册脚本 (和组件平级)
    // index.js
    import Menu from './menu'
    
    Menu.install = Vue => Vue.component(Menu.name, Menu)
    export default Menu

    4.创建一个组件库入口(脚本)
     

    // index.js (在src下方,与main.js平级)
    import Menu from '../packages/menu/index';
    
    const components = [Menu]
    
    const install = function(Vue. opts={}) {
        components.forEach(component => {
          Vue.component(component.name, component)
        })
    }
    
    if (typeof window !== 'undefined' && window.Vue) {
        install(window.Vue)
    }
    
    export default {
        install,
        Menu
    }
    // 若是依赖第三方UI库, 则需要将其引入 以element-ui为例, 需要在以上的代码中添加如下代码
    import Vue from 'vue'
    import ELement from 'element-ui'
    
    Vue.use(Element)
    import 'element-ui/lib/theme-chalk/index.css'

     5. 修改webpack.base.conf.js
      

    export default {
            entry: process.env.NODE_ENV === 'production' ? './src/index.js' : './src/main.js',
            output: {
                path: config.build.assetsRoot,
                filename: 'index.min.js',
                publicPath: process.env.NODE_ENV === 'production'
                  ? config.build.assetsPublicPath
                  : config.dev.assetsPublicPath,
                library: 'Application', // 指定的就是你使用require时的模块名
                libraryTarget: 'umd',  // 指定输出格式
                umdNamedDefine: true // 会对 UMD 的构建过程中的 AMD 模块进行命名。否则就使用匿名的 define
            }
        }
        
        
        library:指定的就是你使用require时的模块名
      libraryTarget:为了支持多种使用场景,我们需要选择合适的打包格式。常见的打包格式有 CMD、AMD、UMD,CMD只能在 Node 环境执行,AMD 只能在浏览器端执行,UMD 同时支持两种执行环境。显而易见,我们应该选择 UMD 格式。
    
      有时我们想开发一个库,如lodash,underscore这些工具库,这些库既可以用commonjs和amd方式使用也可以用script方式引入。
    
      这时候我们需要借助library和libraryTarget,我们只需要用ES6来编写代码,编译成通用的UMD就交给webpack了
    
      umdNamedDefine:会对 UMD 的构建过程中的 AMD 模块进行命名。否则就使用匿名的 define

    6. 修改 webpack.prod.conf.js
     

    // 这里主要修改 plugins中间的配置 主要就保留以下两个插件即可
    plugins: {
        // 关于js的压缩插件
        new UglifyJsPlugin({
          uglifyOptions: {
            compress: {
              warnings: false
            }
          },
          sourceMap: false,
          parallel: true
        }),
        // 关于css的压缩
        new ExtractTextPlugin({
          filename: 'index.min.css'
        }),
    }
    

     7. 修改package.json 文件

    {
        "name": "@styleofpicasso/vue-plugin",  // 插件名称
        "version": "0.0.1", // 插件版本
        "author": "styleofpicasso",
        "main": "dist/index.min.js",  // 打包后的文件入口
        "files": [  // npm 发布的文件包含哪些
          "dist",
          ...
        ],
        "private": false,  // 公开项目,因为组件包是公用的,所以private要改为false
        "keywords": [ // 关键词,可以通过npm搜索你填写的关键词找到你的模块
           "vue",
           "components"
           ...
        ],
        "homepage": "https://xx.github.io/xx/xx-btn/dist/index.html", // 项目官网的url
        "bugs": { // 填写一个bug提交地址或者一个邮箱,被你的模块坑到的人可以通过这里吐槽
            "url": "https://github.com/xx/xx-btn/issues"
        },
        "repository": { // 指定代码所在的仓库地址
            "type": "git",
            "url": "https://github.com/xx/xx-btn.git"
        },
    }

    8. 样式的编译 (主题色编译 —— 支持用户自定义)

    • variable.scss
    $--color: orange !default;  // 这里加上 !default, 是默认色,当用户在项目中自定义了 $--color, 会优先使用用户自定义的
    
    $--static-color: #333 !default;
    ...
    • mixin.scss

     

    • menu.scss  [当然。这里的样式,我们在menu.vue中在写一次,同时用到变量需要将变量scss文件 引入]
    // 具体样式
    .menu {
        color: $--color;
    }
    • index.scss
       
    @import './variable';
    
    @import './menu';
    ....
    


    9. 编译打包 / 测试插件 

    // 编译打包
    npm run build
    
    // 测试插件
    npm pack
    // npm pack 之后,会在当前目录下生成以一个 styleofpicasso-vue-plugin-0.0.1.tgz 文件
    
    // 打开vue项目,并将该文件放在项目的根目录下,并运行以下命令 (这里的路径时绝对路径)
    npm install 路径/styleofpicasso-vue-plugin-0.0.1.tgz
    
    // 安装成功之后,直接在项目中使用该插件,看是否能用,
    import VuePlugin from '@styleofpicasso/vue-plugin',
    Vue.use(VuePluin)
    
    // 若是能用就直接发布到npm官网,再在项目中重新安装npm插件  (这里需要注意要将package.json中关于插件的包安装地址进行清除,否则会一直安装测试包)
    

    10. 发布 npm包


    具体操作,这里就不加说明了,大家都知道

    11. 安装使用

    •  安装
    npm install @styleofpicasso/vue-plugin --save
    或
    yarn add @styleofpicasso/vue-plugin
    • 使用
    import VuePlugin from '@styleofpicasso/vue-plugin'
    Vue.Use(VuePlugin)
    
    // 这里是直接包内的样式及主题
    // import '@styleofpicasso/3d-application/dist/index.min.css';
    
    // 自定义主题色 (创建一个自己的文件 shared.scss, 包含内容如下)
    $--color: 色值  // 按钮鼠标移入色值
    $--static-color: 色值 // 默认色值
    @import '@styleofpicasso/3d-application/src/plugin/package/css/index.scss';
    
    //在入口文件引入
    import '../../css/shared.scss'
    

     

    这里需要注意: 若是基于element-ui开发的组件,  选择直接使用插件的固定主
    需要将element-ui中关于字体的fonts文件夹复制到static文件下,保证引入的样式中不报错
     

    展开全文
  • uniapp作为一个新手来说 上手是很快的,语法和vue,小程序API一样,总结一下踩坑特性 引入问题,接手的时候是二...hubuildx启动、打包的时候自定义语法命令没生效(有时会有) 暂不知代码哪里问题,解决:重启hbuildX
  • vue封装自定义组件并上传到npm

    千次阅读 2020-12-22 11:24:57
    使用vue-cli3搭建团队的组件库并发布到npm 1.安装vue-cli3并创建一个项目 首先我们先安装开发必要的工具集,并创建一个项目: npm发包的常用基础知识
  • Vue-webpack打包教程

    2021-05-12 11:24:01
    "scripts": { "dev": "webpack-dev-server" }, webpack-dev-server自动打包的输出文件(bundle.js),默认放到了服务器的根目录下 自动打包完毕后,默认打开服务器网页 解决:在package.json中的dev指令 webpack 5与...
  • 在其他浏览器可以使用但 打包之后 在ie11 就报错如下 其实这个因为directive 命令要在 new vue 实例之前创建, 如果在 new vue 里面 就会报错 比如这种 方法就是 在 new vue 之前 用 Vue.directive('test-...
  • 过渡,生命周期,自定义指令 一、transition过渡 1.1 单元素过渡 1.2 多元素过渡 1.3 多个组件过渡 1.4 列表过渡 二、vue生命周期,过滤器,自定义指令 2.1 vue生命周期 2.2 过滤器 2.3 vue.swiper 2.4 自定义指令 ...
  • 1.在mian.js中注册,该...在.vue(单文件组件)中加入的new Vue(),这样将会有俩个Vue实例,导致意外发生,建议你将全局组件、插件等都写到main.js中,挂载到一个Vue实例上,而.vue(单文件组件)采用 export default...
  • 作为一名初级前端,每天要学习的东西真的非常多,以前只要有环境打包,都是手动改动url,非常的麻烦,而且上线的时候,很容易忘记修改,bug由此产生,哈哈哈。。。 今天学习的配置环境,希望能给大家作为参考,勿喷...
  • 搭建webpack +babel + vue项目的操作步骤 1. 新建一个存放项目的文件夹 我新建的文件名为demoVue 2. 打开cmd,执行cd指令到该文件夹下 3. 可执行npm init命令,自己配置一下,我这边直接执行npm init -y,使用默认...
  • 补充的知识点Javascript push()向Array的末尾添加若干个元素,pop()则把Array的最后一个元素删除掉; var arr = [1,2]; arr.push('A','B');//返回Array新的长度:4 arr;...//空数组继续pop不会报错
  • 第一步 : 了解环境变量概念 我们可以根目录中的下列文件来指定环境变量: .env # 在所有的环境中被载入 ...当需要为测试环境进行打包的时候 , 我们只需要运行下面指令进行打包 npm run test
  • vue项目打包exe文件

    千次阅读 2020-11-28 11:18:31
    方案一:利用electron直接打包项目 暂未成功,打包完exe会报错 打包方式: (1)DOS窗口命令打包 DOS 下,输入 npm install electron-packager -g全局安装我们的打包神器: cnpm install electron-packager -g (2...
  • 初始化vue项目, 测试服务已经准备(前提已经准备好了)注意: 一键部署 vue2.0~3.0 都可以使用1、在根目录 新建deploy 文件夹:.env.dev类容如下VUE_APP_SERVER_ID=0.env.prod类容如下VUE_APP_SERVER_ID=1index.js 文件...
  • 一、webpack打包指令 npm run build 二、webpack打包后生成dist文件,将dist文件夹中的文件,放在服务器上 1、如果页面空白,报错资源的引用路径不对 解决:找到 config > index.js build: { inde...
  • 因此,当我们从github上爬取别人的vue项目之后如何在本地运行呢?那么进入正题。 2、安装node.js Node.js 是一个运行在服务端的框架,它的底层就使用了 V8 引擎,虽然作用与Java的servlet类似,都能开发动态网页。...
  • electron-vue打包成Mac版本

    千次阅读 2019-12-20 13:52:07
    elelctron-vue官方网址:https://simulatedgreg.gitbooks.io/electron-vue/content/cn/ 一、场景: ...在mac电脑上如何将electron-vue打包成.app文件? 下面是对这个问题作出的操作 1、在项目的pac...
  • 我们在做vue单页应用的时候,会发现配置文件里有procsss.env字段 如果手动修改代码中加载配置文件的路径也可以,但是太麻烦,最重要的是很low 依靠环境变量,标记服务器,这样就可以根据不同的环境,配置不同环境下我们...
  • Vue安装教程

    2021-11-16 11:42:08
    webpack: 它主要的用途是通过CommonJS的语法把所有浏览器端需要发布的静态资源做相应的准备,比如资源的合并和打包 vue init webpack jt01 #此处项目名不能使用大写---可能比较慢,要等 注: jt01 为自定义的 ...
  • 最近用vue写了一些项目,项目写完之后需要打包之后才能放到网上展示,所以在这里记录一下项目打包的过程以及遇到的一些问题。 -------------------------------------------------- 分割线 ---------------------...
  • 自定义指令 一、Vue的生命周期 生命周期就是指一个对象的生老病死的过程。 用Vue框架,熟悉它的生命周期可以让开发更好的进行。 所有的生命周期钩子自动绑定 this 上下文到实例中,因此你可以...
  • v-demo.a.b: 自定义指令+修饰符. 具体看你什么指令了,修饰符的作用大多是给事件增加一些确切的拓展功能,比如阻止事件冒泡,阻止默认行为,访问到原生控件,结合键盘快捷键等等 。 可以自定义修饰符么?也是可以的。...
  • vue项目配置使用typescript教程

    千次阅读 2020-10-26 18:31:46
    本文是vue项目的js升级ts教程,也可以作为vue项目的ts使用教程。 项目背景: vue版本:2.6.11 基于vue-cli4脚手架生成 已配置eslint(配置教程参考:传送门) 一、安装依赖 vue ts基础: npm i -D typescript @vue...
  • 常用Vue指令总结

    2021-01-25 11:08:15
    指令 说明 v-model 双向数据绑定,一般用于表单元素 v-for 对数组或对象进行循环操作 v-on 绑定事件,用法v-on:事件=“函数” v-show/v-if 用来显示或隐藏元素,v-show是通过display实现,v-if是每次删除...
  • @vue/cli脚手架2.1 @vue/cli 脚手架介绍@vue/cli的好处2.1_@vue/cli安装2.1 @vue/cli 创建项目启动服务2.2 @vue/cli 目录和代码分析2.3 @vue/cli 项目架构了解2.5_@vue/cli 自定义配置2.6_eslint了解2.6 @vue/cli ...
  • 可以执行一下代码,在vue-cli中自有打包指令,进行打包,但是为了打包后的大小考虑,还需要在项目的开始前以及结束后,进行相应的操作,对项目打包进行优化,是项目的所占体积变小 npm run build //使用npm打包 ...
  • 1.Angular开发 与 Vue开发相同, 都需要安装脚手架; 然后使用脚手架来生成项目包. 2.node版本需要最新版本; //版本在12以上即可 a).npm默认的下载源在国外, 会导致国内使用较慢甚至无法下载 检查当前下载源, npm ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,771
精华内容 708
关键字:

vue自定义指令打包之后报错

vue 订阅