精华内容
下载资源
问答
  • 反倒是一直在使用的vue.js(2.x)框架因为业务需求再加上看之前同事写的项目研究了一下全局手动挂载组件的开发(当然了,最近 vue 3.0 也是发布了 Beta 版本,也不知道以后这一块的写法是否会发生变化)。...

    前言

    之前一段时间笔者因为换城市发展换工作等一系列不愉快的原因博客停更了==|,原本的计划是每个月至少写一篇原创的文章出来了,现在也是断了几个月;当然在过去的几个月时间里笔者也没闲着,主要学习了React框架的一些基础知识,不过现在学习的还不是很熟练,所以暂时也是出不了成体系的文章出来。反倒是一直在使用的vue.js(2.x)框架因为业务需求再加上看之前同事写的项目研究了一下全局手动挂载组件的开发(当然了,最近 vue 3.0 也是发布了 Beta 版本,也不知道以后这一块的写法是否会发生变化)。

     

    1. 定义及相关实例

    挂载,这个词汇我们在查看 vue 官方文档是总是会看到,但是概念上还是比较模糊的,是属于那种我们大概知道意思但是又不是很清晰的了解的概念。笔者在知乎上找到了一个比较靠谱回答,是关于 React 中挂载的概念:

    我们把 React.js 将组件渲染,并且构造 DOM 元素然后塞入页面的过程称为组件的挂载。

    而在HTML中文网上有关于 vue 中挂载的概念:

    将组件渲染,并且构造 DOM 元素然后塞入页面的过程称为组件的挂载。

    虽然个人觉得这个表述还不是很书面,但是已经比较易懂了。所谓的全局手动挂载组件,是区别于一般我们在 vue 中写的模板用于框架自动挂载展示页面,具体我们可以看 vue 的生命周期的经典图:

     如上,详见绿框部分,有两个黄色背景的判断逻辑:Has "el" option? Has "template" option?  这两个意思也比较好懂,第一个意为在初始化一个 vue 实例的时候,传入的 option 参数是否含有 el 属性,如果有,则会直接进入下一步判断(此时说明 vue 中的模板内容将会被自动挂载到 el 属性所在的 div 上),而如果没有 el 属性,则 vue 中模板的内容将会在 vm.$mount(el) 函数被调用的时候挂载到参数 el 上。之后会判断是否有 render 函数,若有则会渲染 render 中的虚拟DOM,若没有 render 则判断是否有 template 选项,若有则挂载 template 中的模板,若没有则 Compile el's outerHTML as template(获取 el 及其子内容作为模板)。

    举例:比如在我们每个 vue 项目都会存在的 @/main.js 入口文件中,就有相关实例。

    import Vue from 'vue'
    import App from './App'
    import router from './router'
    
    new Vue({
      el: '#app',
      router,
      components: { App },
      template: '<App/>'
    })

    如上,我们在项目中创建的 vue 实例(一般是脚手架生成),传入 el 选项,template 选项,那么最终 vue 会把 App 中的模板内容挂载到 id 为 app 的dom节点上,也就是一般我们项目中的 index.html 文件中:

        <body>
            <noscript>
                <strong>Please enable JavaScript to continue.</strong>
            </noscript>
            <div id="app"></div>
            <!-- built files will be auto injected -->
        </body>

     而在没有传入 el 选项的时候呢,如下:

    import Vue from 'vue'
    import router from '@/router.js'
    
    import App from './App'
    import store from './store'
    
    const app = new Vue({
      router,
      store,
      render: h => h(App)
    })
    
    app.$mount("#app")
    
    
    

    最终将会在调用 vm.$mount 方法的时候将 render 函数中的内容挂载到 app dom上,其作用和刚才第一种写法是一样的。

    因此,手动挂载即是我们在 vue 项目开发时调用 $mount 函数进行组件的挂载过程,一般我们将这样的组件用于全局注册,因而也叫全局手动挂载。比如 element/iview/antD vue 等第三方组件库中的 Message , Spin, Loading 等公共组件都有手动挂载的设计。

     

     

     这是 iview 官方文档在介绍 Message 组件的说明,在使用 JS 直接调用相关方法使用组件,它隐式的创建和维护了 vue 组件,也就是调用时手动挂载了 vue 组件。这么写的好处是不用提前在需要使用该组件的地方写 HTML 到<template>,我们可以很方便的在 JS 逻辑代码里调用,甚至在一些公共 JS文件中调用,比如在封装了 api 请求的js文件中调用。

     

    2.需求背景

    由于我们的项目在很多页面都需要判断用户是否登录,若用户未登录则弹出登录弹窗供用户登录,如果按一般的做法就需要在所有需要展示登录的页面加入登录弹窗组件:

     

     

     显然这样会麻烦一些,如果我们能手动挂载该组件,在需要显示弹窗的地方直接用一句话搞定肯定更方便很多:this.$loginPopup(). 那么具体应该怎么处理呢?

    3. 组件开发

    首先我们已经写好了这个登录组件:login.vue,那么相当于这个组件的模板内容已经不需要重新修改了,只需要在该组件所在文件夹创建一个 index.js 文件,在该文件中将 login 组件用 Vue.install 方法暴露出来。

    <!-- login.vue 文件的部分结构 -->
    <template>
      <div class="loginView">
        <Modal
          v-model="innerShowPopup" 
          :footer-hide="true" 
          :scrollable="false"
          :closable="false"
          :z-index="900"
        >
          <login-area :return-url="returnUrl"></login-area>
        </Modal>
      </div>
    </template>
    import Vue from 'vue'
    import loginPopupComponent from './login.vue'
    
    import i18n from '@/i18n/index.js'
    
    
    const Login = {
      install (Vue, options) {
        Vue.prototype.$loginPopup = function (options) {
          const LoginConstructor = Vue.extend(loginPopupComponent)
          const div = document.createElement('div')
          document.body.appendChild(div)
          const vm = new LoginConstructor({
            propsData: options,
            i18n
          }).$mount(div)
          vm.innerShowPopup = true
          // console.log('vm', vm)
          // return vm.login()
        }
      }
    }
    
    export default Login
    

    关于 Vue.install ,官方文档(https://cn.vuejs.org/v2/guide/plugins.html#%E5%BC%80%E5%8F%91%E6%8F%92%E4%BB%B6)有比较详细的解释:

    Vue.js 的插件应该暴露一个 install 方法。这个方法的第一个参数是 Vue 构造器,第二个参数是一个可选的选项对象。

    说白了就是我们开发 vue 插件的时候得调用这个方法,这样组件才能被 Vue.use() 方法调用。关于 Vue.use 方法

    安装 Vue.js 插件。如果插件是一个对象,必须提供 install 方法。如果插件是一个函数,它会被作为 install 方法。install 方法调用时,会将 Vue 作为参数传入。 

     在上述 index.js 代码中 ,loginPopupComponent 就是我们已经写好的 login.vue 组件,它需要被传入 Vue.extend 方法生成对应的构造函数,Vue.extend来自官方的解释及示例:

    使用基础 Vue 构造器,创建一个“子类”。参数是一个包含组件选项的对象。

    // 创建构造器
    var Profile = Vue.extend({
      template: '<p>{{firstName}} {{lastName}} aka {{alias}}</p>',
      data: function () {
        return {
          firstName: 'Walter',
          lastName: 'White',
          alias: 'Heisenberg'
        }
      }
    })
    // 创建 Profile 实例,并挂载到一个元素上。
    new Profile().$mount('#mount-point')

    在生成 LoginConstructor  的登录组件构造函数后,我们通过 new LoginConstructor() 的方式创建一个 vue 实例,其中的 propsData 参数就是我们可以传入组件的 props 对象合集。

    这里需要特别注意的一个坑是 i18n 国际化的问题。这个问题可能在很大业务场景下遇不到,因为我们做的项目是需要支持多语言显示的,故在 login.vue 组件中写的 label 标签名都是从 i18n 中取的变量名,在使用手动挂载时如果没有显式将 i18n 配置传入构造函数中,那么最终在手动挂载函数时会报错,因为找不到变量对应的值。

    最后是挂载点的问题,一般作为全局组件来说,我们可以利用 JS 的 createElement 函数生成一个空的 div 标签,将对应vue 实例挂载到该div标签上。之后需要将该组件在 main.js 文件中进行全局注册:

    /**
     * 全局注册一个登录弹窗组件,在之后需要调用登录弹窗时可直接调用 this.$loginPopup()
     */
    Vue.use(Login)

    这样在之后的 vue 页面中我们就可以随时调用登录弹窗组件了,这样会方便不少。

    最终的效果

     

    4. 总结

    总的来说,Vue组件的手动挂载就是 vue 插件开发的一种方式,平时虽然这类组件比较少但是在特定场景和业务下是非常有用的,大部分是为了方便为项目添加一个全局类的功能同时又不想影响已有页面的很多结构。另外,手动挂载全局组件也更加方便相关组件的修改维护。

     

    参考:

    https://cn.vuejs.org/v2/guide/plugins.html#ad

    https://blog.csdn.net/weixin_34326179/article/details/91478104

    https://m.html.cn/qa/vue-js/16913.html

    https://www.zhihu.com/question/263950486

    https://www.iviewui.com/components/message

    展开全文
  • vue手动刷新视图以及其他小问题

    千次阅读 2020-03-30 22:24:38
    最近把手头上一个使用angularJS+jquery各种七七八八组件写的页面拿vue+elementUI重写了一边, 真是极度丝滑, 记录一些vue和elementUI的小问题 1.如果vue中的数据结构比较庞大的话, 十分有可能会出现model更新而视图不...
    最近把手头上一个使用angularJS+jquery各种七七八八组件写的页面拿vue+elementUI重写了一边, 真是极度丝滑, 记录一些vue和elementUI的小问题

    1.如果vue中的数据结构比较庞大的话, 十分有可能会出现model更新而视图不更新/model和视图都不更新也不报错的情况, 此时需要手动刷新vue的数据, 在change或click事件中, 使用this.$forceUpdate()手动刷新视图

        //像这样
        changeSef: function () {
           //手动刷新视图
           var that = this;
           that.$forceUpdate();
        },
    

    2.在vue中使用setTimeout

    //错误示范
    setTimeout(bidOrderInit, 200);
    //上面那样是不行的,网上查了下, 大致是说在setTimeout中this指向window对象, 
    //于是乎被定时的方法中就使用不到vue的this对象了
    //正确示范
    //可以无视对ie的支持时
    setTimeout(()=> {
      this.bidOrderInit();
    }, 200);
    //需要兼容ie时
    setTimeout(function () {
      this.bidOrderInit();
    }, 200);
    
    展开全文
  • 当网络情况不好的时候,这个组件还需要进一步的优化 前置条件 在你的index.html页面上加载百度地图js(获取ak) 正确安装了vue 使用vue-cli可以快速开发 &lt;script type="text/javascript" src...

    这是一个h5页面–

    效果图

    录图的时候网络条件不是很好,wifi卡了,所以数据加载有点慢。当网络情况不好的时候,这个组件还需要进一步的优化

    前置条件

     <script type="text/javascript" src="http://api.map.baidu.com/api?v=2.0&ak=yourAK"></script>
    

    功能点分解

    1. 分析数据
    2. 实现css布局
    3. 挂载百度map
    4. 定位当前位置
    5. 获取周边poi
    6. 搜索提示
    7. 点击右下角图标重新定位到当前位置
    8. 固定中心点,拖拽地图选择位置

    分析数据

    根据UI图分析组件需要用到哪些数据。

        data(){
          return {
            map:null,//实例化map
            searchValue:"",//搜索model
            currentAddress:"",//当前定位的地址
            point:{},//当前地址的经纬度
            poiKeyword:"",//周边的关键词,用来搜索,从adress中获取street拼接
            potentialLocation:[],//周边信息
          }
        }
    

    css布局

    这样的布局很简单,请随意发挥

    挂载百度map

    initMaps(){
            this.map = new BMap.Map("map");
            let mPoint = new BMap.Point(116.404, 39.915);//天安门
            this.map.centerAndZoom(mPoint,18);
           }
    

    为了确保dom成功创建了,我们在nextTick中进行初始化

    mounted(){
          this.$toast({text:"点击或拖动选址~",position:"top"});//提示信息
          this.$nextTick(()=>{
            this.initMaps();//调用初始化函数
          })
    

    到这里我们应该能在idmap中的div里能够看到地图了

    定位

    我们调用百度提供的api进行定位,这里api定位的内部实现我猜测是基于h5的navigator。
    在这里插入图片描述
    根据警告提示,我们进去源码看看
    在这里插入图片描述
    警告信息说的是需要安全的origin,这里由于是在本地开发环境我们可以忽略这个警告。到了线上还是需要https的,不然遇到dns劫持也是很麻烦的。
    好的,现在实现locate方法用于定位:

     locate(){
            let map = this.map;
            let geolocation = new BMap.Geolocation();
            const vm = this;
            geolocation.getCurrentPosition(function(r){
              if(this.getStatus() === BMAP_STATUS_SUCCESS){
                let mk = new BMap.Marker(r.point);
                map.addOverlay(mk);
                map.panTo(r.point);
              }else {
                console.log('failed ',this.getStatus());
              }
            });
    

    这里我们就成功定位到了当前所在位置,当然别忘记了在mounted方法里调用这个方法了。

    this.$nextTick(()=>{
            this.initMaps();
            this.locate();
          })
    

    显示当前位置

    刚刚在locate方法中获取到了当前的point值,也就是经纬度。那么如何显示地址信息呢?locate中回调函数参数r其实是包括了address信息的,但是!有时候address精确度只是到了城市级别–比如我这里console.log(r);打印出来的信息如下:
    在这里插入图片描述

    为了解决这个问题,我们需要从拿到的point对象入手,逆地址解析一次。
    这里我们创建一个analyze函数调用百度的getLocation方法进行解析

          /**
           * Attention: 解析地址会有异常--有时候会解析正确,有时候只会解析到区
           * @param point lng and lat
           */
            analyze(point){//point:{lat:"",lng:""}
            const geoc = new BMap.Geocoder();
            geoc.getLocation(point, rs=>{
              this.point = rs.point;
              this.currentAddress = rs.address;
              this.poiKeyword = rs.street||rs.address;
            });
          },
    

    并利用vue的数据响应相应的更新当前位置,当前经纬度,当前poiKeyword
    poiKeyword有值了应该做什么呢?我们就可以开始根据point来搜索周边,提供周围的位置信息啦。
    那么这里我们为poiKeyword创建一个监听器,进行实时操作。

        watch:{
          poiKeyword(n){
            this.getAroundPOI(["栋","店","小区","学校","餐饮",n]);//n就是最新值
          }
        }
    

    实现getAroundPOI函数

    在监听器中我们提供了poi的搜索关键词,于是我们可以调用百度地图LocalSearchsearchNearby函数。这里我们搜索周围方圆1000m的周边数据。

    getAroundPOI(keyword){
            let map = this.map;
            let mPoint = new BMap.Point(this.point.lng, this.point.lat);
            let vm = this;
            let local =  new BMap.LocalSearch(map, {
              onSearchComplete(results){
                if (local.getStatus() === BMAP_STATUS_SUCCESS){
                  let temp = [];
                  results.forEach(item=>{
                    temp = temp.concat(item.Ar);
                  });
                  vm.potentialLocation = temp;//更新ui
                }else{
                  console.warn("get poi error ,code -> ",local.getStatus());
                }
              }
            });
            local.searchNearby(keyword,mPoint,1000);
          },
    

    onSearchComplete回调中更新potentialLocation的值之后vue会帮助我们更新这部分ui

    搜索提示

    百度地图的搜索提示其实很简单,只需要创建一个自动装填对象。搜索下拉提示框会根据你传入的input参数(input id)进行定位,宽度与input相同。

    getSuggestion(){
            let ac = new BMap.Autocomplete({"input" : "suggestId","location" : this.map});
            ac.addEventListener("onconfirm", e=> {
              let _value = e.item.value;
              this.searchValue = _value.province + _value.city + _value.district + _value.street + _value.business;
              this.setPlace(this.searchValue);
            });
          },
    

    在上述代码中,我们定义了自动装填对象的监听器(点击下拉列表项时触发),并更新了input的值,在vue中我们一般用v-model进行双向绑定。
    获取到了地址信息之后,我们调用了setPlace方法并传入了搜索值。
    setPlace方法主要用作给地图重定位,移动地图中心到搜索值所在地点。

     setPlace(val){
            let map = this.map;
            map.clearOverlays();
            const vm = this;
            let local = new BMap.LocalSearch(map, {
              onSearchComplete(){
                let pp = local.getResults().getPoi(0).point;
                map.centerAndZoom(pp, 18);
                map.addOverlay(new BMap.Marker(pp));
                vm.analyze(pp);
              }
            });
            local.search(val);
          }
    

    同时,注意在上面的代码中我们调用了analyze方法,用来更新周边信息。为什么能更新呢,忘了就往上翻回去看看analyze方法是怎么实现的吧。

    重定位及拖拽中心

    为了实现这个需求,首先我们要想办法地图上的自定义控件。自定义控件很麻烦,而且也会影响网页性能,所以我们应该另辟蹊径。论坛上其实有更简单的方法,这里我将论坛中的思路实现了。
    关键就在于将控件看成网页的dom去相对于百度canvas地图进行定位。
    看一下dom结构:

    <div class="map-wrapper">
          <div id="map"></div>
          <img class="position" src="../../assets/icon/position.svg" alt="position">
          <img class="nowposition" @click="locate" src="../../assets/icon/nowposition.svg" alt="nowposition">
        </div>
    

    以及css

     .map-wrapper{
          height: 50%;
          position: relative;
    
          #map{
            height: 100%;
          }
          img{
            width: 32px;
            object-fit: contain;
          }
          .position{
            position: absolute;
            left: 50%;
            top: 50%;
            transform: translate(-50%,-75%);//The bottom of the icon is centered,75  = 50(center) + 25(top)
            z-index: 100;
          }
          .nowposition{
            position: absolute;
            right: 20px;
            bottom:20px;
            z-index: 100;
          }
          }
    

    这里要注意的一点就是利用position以及translate(-50%,-50%)居中以后为什么要上调25%?因为中间的图标是尖尖的,肉眼更倾向于利用图标的底部(那个尖尖)进行定位。我们给它的样式是正方形,并且是contain的,所以x轴是正好居中的不用管。但是y轴的问题是这样做仅仅是将y的中心点放在地图的中心位置,会有一点点的纬度偏差。我们应该与肉眼保持一致,因此需要将底部位于地图的正中心。因此我们还要上调25%。(自身高度的一半,因为就剩一半了)

    为了能够让中心点定位,我们还需要给map注册一个监听器。
    initMaps方法中加上一个监听器。

     this.map.addEventListener('dragend',()=>{
              let pixel = this.map.pointToOverlayPixel(this.map.getCenter());
              let point = this.map.overlayPixelToPoint({x:pixel.x,y:pixel.y});
              this.analyze(point);
            })
    

    在方法的回调里再调用analyze方法重新获取poi,实时更新周边位置信息。

    源码

    <template>
      <div class="ys-map">
    
        <div class="map-wrapper">
          <div id="map"></div>
          <img class="position" src="../../assets/icon/position.svg" alt="position">
          <img class="nowposition" @click="locate" src="../../assets/icon/nowposition.svg" alt="nowposition">
        </div>
    
        <div id="tips">
          <AddressItem :title="'当前位置'" :address="currentAddress" :extra="'(以图上标记位置为准)'"/>
          <AddressItem v-for="(item,index) in potentialLocation" v-bind:key="index" :title="item.title" :address="item.address" @click.native="selectAddress(item)"/>
          <div v-if="potentialLocation.length===0">{{point.lng}},{{point.lat}}</div>
        </div>
    
        <div class="ys-search-address">
          <img class="back" src="../../assets/icon/back.svg" alt="back" @click="onBackClick">
          <div class="ys-search-wrapper">
            <input type="text" v-model="searchValue" title="" id="suggestId" placeholder="定位不准?试试手动输入">
            <img src="../../assets/icon/close.svg" alt="search" @click="searchValue=''">
          </div>
          <a class="okBtn" href="javascript:;" @click="onOkClick">确定</a>
        </div>
    
        <div class="search-tips" id="result">
          tips
        </div>
      </div>
    </template>
    
    <script>
      import AddressItem from "./AddressItem";
      export default {
        name: "Map",
        components: {AddressItem},
        mounted(){
          this.$toast({text:"点击或拖动选址~",position:"top"});
          this.$nextTick(()=>{
            this.initMaps();
            this.locate();
            this.getSuggestion();
          })
        },
        methods:{
          initMaps(){
            this.map = new BMap.Map("map");
            let mPoint = new BMap.Point(116.404, 39.915);//Tiananmen Square
            this.map.centerAndZoom(mPoint,18);
            this.map.addEventListener("click", this.onMapClicked);
            this.map.addEventListener('dragend',()=>{
              let pixel = this.map.pointToOverlayPixel(this.map.getCenter());
              let point = this.map.overlayPixelToPoint({x:pixel.x,y:pixel.y});
              this.analyze(point);
            })
          },
          locate(){
            let map = this.map;
            let geolocation = new BMap.Geolocation();
            const vm = this;
            geolocation.getCurrentPosition(function(r){
              if(this.getStatus() === BMAP_STATUS_SUCCESS){
                let mk = new BMap.Marker(r.point);
                map.addOverlay(mk);
                map.panTo(r.point);
                vm.analyze(r.point);
              }else {
                console.log('failed ',this.getStatus());
              }
            });
            //loading--
          },
          getAroundPOI(keyword){
            let map = this.map;
            let mPoint = new BMap.Point(this.point.lng, this.point.lat);//h5 112.983323,28.141431
            let vm = this;
            let local =  new BMap.LocalSearch(map, {
              onSearchComplete(results){
                if (local.getStatus() === BMAP_STATUS_SUCCESS){
                  let temp = [];
                  results.forEach(item=>{
                    temp = temp.concat(item.Ar);
                  });
                  vm.potentialLocation = temp;
                }else{
                  console.warn("get poi error ,code -> ",local.getStatus());
                }
              }
            });
            local.searchNearby(keyword,mPoint,1000);
          },
          /**
           * Attention: 解析地址会有异常--有时候会解析正确,有时候只会解析到区
           * @param point lng and lat
           */
          analyze(point){//point:{lat:"",lng:""}
            const geoc = new BMap.Geocoder();
            geoc.getLocation(point, rs=>{
              this.point = rs.point;//===r.point
              this.currentAddress = rs.address;
              this.poiKeyword = rs.street||rs.address;
            });
          },
          /**
           * search tips
           */
          getSuggestion(){
            let ac = new BMap.Autocomplete({"input" : "suggestId","location" : this.map});
            ac.addEventListener("onconfirm", e=> {
              let _value = e.item.value;
              this.searchValue = _value.province + _value.city + _value.district + _value.street + _value.business;
              this.setPlace(this.searchValue);
            });
          },
          selectAddress(item){
            //todo: return item the same as onOkClicked function
          },
          setPlace(val){
            let map = this.map;
            map.clearOverlays();
            const vm = this;
            let local = new BMap.LocalSearch(map, {
              onSearchComplete(){
                let pp = local.getResults().getPoi(0).point;
                map.centerAndZoom(pp, 18);
                map.addOverlay(new BMap.Marker(pp));
                vm.analyze(pp);
              }
            });
            local.search(val);
          },
          onMapClicked(e){
            console.log(e);//todo: get point with dialog and return
          },
          onBackClick(){
            //todo: cancel
          },
          onOkClick(){
            //todo: get this address and return.
            console.log("已选中当前位置!");
            console.log(this.currentAddress,this.point)
          }
        },
        data(){
          return {
            map:null,
            searchValue:"",
            currentAddress:"",
            point:{},
            poiKeyword:"",
            potentialLocation:[],
          }
        },
        watch:{
          poiKeyword(n){
            this.getAroundPOI(["栋","店","小区","学校","餐饮",n]);
          }
        }
      }
    </script>
    
    <style lang="less" scoped>
      .ys-map{
        height: 100%;
        overflow: hidden;
        position: relative;
        .map-wrapper{
          height: 50%;
          position: relative;
    
          #map{
            height: 100%;
          }
          img{
            width: 32px;
            object-fit: contain;
          }
          .position{
            position: absolute;
            left: 50%;
            top: 50%;
            transform: translate(-50%,-75%);//The bottom of the icon is centered,75  = 50(center) + 25(top)
            z-index: 100;
          }
          .nowposition{
            position: absolute;
            right: 20px;
            bottom:20px;
            z-index: 100;
          }
    
        }
        #tips{
          width: 100%;
          height: 50%;
          overflow-y: scroll;
          position: relative;
          padding: 1px 12px;
        }
        .ys-search-address{
          position: absolute;
          left: 0;
          top: 0;
          width: 100%;
          height: 50px;
    
          background: #f2f2f2;
          padding: 8px 0;
          display: flex;
          justify-content: space-around;
          align-items: center;
    
          .back{
            width: 20px;
            object-fit: contain;
          }
          .okBtn{
            background: #FFDF5C;
            padding: 5px 12px;
            border: 1px solid #ffcf6e;
            color: #333;
            border-radius: 8px;
          }
          .ys-search-wrapper{
            width: 68%;
            border-radius: 20px;
            background: rgba(0, 0, 0, .06);
    
            display: flex;
            align-items: center;
            input{
              padding: 8px 12px;
              background: transparent;
    
              width: 90%;
              height: 100%;
            }
    
            img{
              width: 12px;
              object-fit: contain;
            }
          }
        }
        .search-tips{
          position: absolute;
          left: 0;
          top: 50px;
          background: rgba(255,255,255,.8);
          border:1px solid #C0C0C0;
          height:auto;
          display:none;
        }
      }
    </style>
    
    
    展开全文
  • Vue项目中用百度地图实现城市定位

    千次阅读 2020-12-23 12:08:58
    说明:本文主要是介绍如何在Vue项目中接入百度地图并定位当前城市,更深层次的内容稍后有空整理。 可能还有更牛的实现方案,目前我这里记录的是我自己跑通的一个版本,希望对你有所帮助,仅供参考。 Vue项目...

    说明:本文主要是介绍如何在Vue项目中接入百度地图并定位当前城市,更深层次的内容稍后有空整理。

     

    可能还有更牛的实现方案,目前我这里记录的是我自己跑通的一个版本,希望对你有所帮助,仅供参考。

     

    Vue项目运行环境:Vue 2.0,Vue Cli 3.0

     

    步骤如下:

    步骤一:登录 百度地图开放平台 在 控制台---->应用管理---->我的应用 下面创建一个应用。目的是获取 ak

    获取ak

    步骤二:在public文件夹的index.html文件中导入百度地图,拼上你的ak

    引入百度地图js

     

    这个地址链接是百度地图给的,你可以点击这个传送门去百度地图官网查看出处

     

    步骤三:在项目的根目录中创建vue.config.js文件,如果有vue.config.js文件的话,直接添加以下代码即可。

    vue.config.js文件在VueCli 3.0之后就不再默认创建了,有用到这个文件的时候,需要我们手动创建。

    module.exports = {
      configureWebpack: {
        externals: {
          'BMap': 'BMap' // 百度地图配置
        }
      }
    }
    

    配上截图

    vueconfigjs中配置百度地图

     

    步骤四:接下来就是具体的代码实现了。

    接下来会介绍两种实现方案。

    方式一(推荐使用):单独封装js工具文件实现地址获取。

    1,在src文件夹下新建util文件夹,然后在util文件夹中新建getUserLocation.js文件。

    注:这个util文件夹,可以存放所有自己封装的工具js文件,不单单是getUserLocation.js这一个定位相关的文件。

    代码和截图如下:

    // 获取当前城市
    const getCurrentCityName = function() {
      return new Promise((resolve, reject) => {
        let myCity = new BMap.LocalCity();
        myCity.get((result) => {
          let geoc = new BMap.Geocoder();
          geoc.getLocation(result.center, (rs) => {
            // rs 中携带着所有的定位信息,这里只获取了城市(city)和所在的区(district)
            let addComp = rs.addressComponents;
            let result = addComp.city + addComp.district;
            resolve(result);
          });
        }, {enableHighAccuracy: true});
      });
    }
    export default getCurrentCityName;

    封装定位js代码

    2,在组件中引入并调用上述文件中封装的方法。

    截图如下:

    使用代码演示

     

    不出意外的话,页面通过locationMsg属性即可显示位置信息,例如:北京市丰台区

    方式一结束。

     

    方式二:直接在组件中进行定位。

    直接在组件中使用以下代码即可定位成功,这种方式耗时比方式一要长。

    代码及截图如下:

    ......
    mounted() {
        // 获取位置信息
        this.getCity();
      },
      methods: {
        getCity() {
          const getLocation = new BMap.Geolocation();
          var _this = this;
          getLocation.getCurrentPosition((position) => {
            // position中存放所有的定位数据
            console.log(position);
            // 这里获取的是城市和省
            let city = position.address.city;
            let province = position.address.province;
            _this.locationMsg = province + city;
          }, () => {
            _this.locationMsg = '定位失败!';
          }, {provider: 'baidu'});
        }
      }
    ......

    直接在组件中获取定位

    注:这里的_this其实是没有必要的,可以直接使用this,之前没有使用箭头函数,就使用了_this,后来改成箭头函数之后,没有修改_this相关的代码。当然按照上述代码写也没有问题。

     

    不出意外,就可以在组件中通过locationMsg属性获取到位置信息了。

    方式二使用方法结束。

     

    我在实际运行中发现第二种使用方式会比第一种方式的耗时长一些,因此建议使用方式一实现。

     

    本章全部内容结束,希望可以帮到你。

     

    如果文章对你有帮助,碰巧想请我喝杯咖啡,可以点击这里。O(∩_∩)O哈哈~

    展开全文
  • Vue项目运行环境:Vue 2.0,Vue Cli 3.0 步骤一:登录 百度地图开放平台 在 控制台---->应用管理---->我的应用 下面创建一个应用。 目的是获取 ak 步骤二:在public文件夹的index.html文件中 导入百度地图,...
  • vue实现省市区三级联动地址选择

    千次阅读 2019-09-12 17:10:42
    之前由于产品需求,自己去实现了省市区三级联动的选择,但是总感觉有所欠缺,后来花了一点时间整理,特此分享下我的思路,望大佬们指教。 前端页面 要什么废话 直接上代码 <style> .address_select { ...
  • 基于Vue+element ui+axios的三级联动,手动创建静态的json文件,axios获取json文件,并获取数据
  • 这篇文章主要介绍了vue vant Area组件使用详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧官网中给的内容太少,引入官网中的Area...
  • vue 地图 切换地图组件 Vue2传单 (Vue2Leaflet) Vue2 component that helps with leaflet interaction Vue2组件,有助于小叶交互 如何用标记显示地图 (How to display a map with a marker) Register Map and ...
  • 基于vue2实现省市联动

    千次阅读 2018-05-23 11:58:56
    vue实现级联选择器还是很简单,如果我们用到iview这个UI组件库,其中Cascader级联选择组件中对数据有较严格要求,每项数据至少包含 value、label 两项,子集为 children,以此类推。12&lt;template&gt; ...
  • 今日内容详细:组件化开发Vue自动化工具的安装单文件组件的使用templatescriptstyle案例-点击加减数字组件的嵌套练习:选项卡和天气系统的封装知乎视频​www.zhihu.com5. 组件化开发5.1 组件[component]组件...
  • 默认框架没有引用Cascader组件,需要自己手动引用,引用方式: 打开/src/core/lazy_use.js, import { ... Cascader } from 'ant-design-vue' ... Vue.use(Cascader) 这样在Vue页面上就能直接
  • vuecli实现仿写饿了么

    千次阅读 2020-04-22 19:06:44
    仿写饿了么是一个不错的用来锻炼vue的方式,我仿写的饿了么还是比较浅显的,没有使用饿了么提供的api,数据就是自己手写的几条json用json-server打开,只是实现基本功能,唯一一个第三方api就是百度地图的获取的定位...
  • vue组件封装(1)

    2021-01-24 19:28:03
    vue组件封装 betterscroll滚动 vue-scroller封装 发送短信验证码 地址弹窗的封装 可编辑框组件 单图片预览 多图片预览 抽屉组件 日历组件 分页组件 betterscroll滚动 <template> <div ref="wrapper"> <slot></slot...
  • vue实现最简易table增删改查

    千次阅读 2020-04-06 22:54:58
    一、环境准备 编译器:Webstorm ... vue 1.安装Node.js 菜鸟教程:https://www.runoob.com/nodejs/nodejs-install-setup.html 2.安装npm Windows系统cmd: npm install npm -g 使用淘宝镜像: npm install -g ...
  • vue组件中如何写内部样式

    千次阅读 2018-11-15 09:41:44
    Vue: scoped 样式与 CSS Module 对比前言Scoped 样式模块式 CSS总结 前言 前两天在不同的城市感受了时间。今日早读文章由@西楼听雨翻译分享。 正文从这开始~~ 在现代化的 Web 开发中,CSS 还远未完美,这一点...
  • 仿百度搜索实现的一个搜索功能控件,主要包括:自动提示、搜索历史等功能 源码工程地址:示例源码 效果图 安装 由于源码未创建npm包,所以请手动下载工具源码使用,谢谢!~ 使用方式 import {tool_type_enum} from...
  • 前言《Vue组件库工程探索与实践》系列文章第三篇来了,这篇聊聊组件库单元测试和持续集成功能的实现。今日早读文章由@京东用户体验设计部(JDC)@FransLee投稿分享。正文从这开始~~单元测试是软件工程领域的一个重要...
  • 最近项目上线部署完毕闲着没事, 感觉mint-ui里面的picker组件和自己的需求有冲突,所以就基于它自己封装了一个省市联动组件! 1:父组件调用子组件的地方 注册组件什么的就不说了  &lt;mt-button type=&...
  • 此文为vue进阶篇,包含vue路由、组件、axios请求以及结合springboot开发实例 入门篇链接地址https://blog.csdn.net/qq_41157588/article/details/115085686 代码完整无水分,供学习参考,更多了解信息请看文末....
  • 说明:本文主要是介绍如何在Vue项目中接入百度地图并定位当前城市,更深层次的内容稍后有空整理。 可能还有更牛的实现方案,目前我这里记录的是我自己跑通的一个版本,希望对你有所帮助,仅供参考。 Vue项目...
  • vue+高德地图实现地图搜索及点击定位

    千次阅读 热门讨论 2019-06-18 13:34:31
    最近有个需求是实现一个使用地图搜索定位的功能,在网上参考了下其他的文章,感觉不是很完善,自己整理了一下,可以实现点击定位,搜索列表定位等功能,可能有些地方是多余的,需要的自己看着改下 <script type=...
  • Element:一套通用组件库的开发之路Element 是由饿了么UED设计、饿了么大前端开发的一套基于 Vue 2.0 的桌面端组件库。今天我们要分享的就是开发 Element 的一些心得。官网:...
  • vue调用百度地图API实现点击相应位置切换地图定位 1、需求分析 在页面显示地图,初始状态显示上海市,地图上有特定地点的标注。 左侧为建筑(地点)列表,点击某个地点右侧地图定位到其地理位置并显示具体信息。 2...
  • vue实现百度地图的引用(根据输入框输入内容获取详细地址) 代码内容参考:https://www.cnblogs.com/shuaifing/p/8185311.html 最终实现效果 第一步:在index.html中引入百度地图api &amp;amp;lt;script type...
  • Vue 实现一个中国地图

    2019-10-07 02:44:41
    参考:... 重点:如何引入中国地图js文件,china.js require('echarts/map/js/china') # 安装vue-cli npm install vue-cli -g # 初始化项目 vue init webpack china-map # 切到目录下 ...
  • vue-weather基于vue.js 2.0的百度天气应用。说明初学vue,在看完一个简单的视频教程和走两遍完官方文档之后仍然感觉云里雾里,知其然不知其所以然(虽然现在好了点)。请教了高手之后人家都说学习新东西的最好方法不...
  • vue省市二级联动

    2021-04-14 21:37:45
    <select name="" id="" v-html="htmlStr"></select> </div> </template> </body> <script src="/js/vue.min.js"></script> <script> Vue.component("proCity", { template: "#temp1", /** * @name data 组件中的数据...
  • uni-app框架城市选择

    千次阅读 2020-12-31 07:29:04
    最近的工作,以小程序为主,考虑到当前的项目以后也会发布APP,所以就选择了一款跨平台的开发...以前还没有入VUE2.0的坑,所以学起来比较吃力,前两天项目中要用到一个城市的定位与选择的功能,真是让我头大了,不过还没拦...
  • 为梦想而创作:JavaWeb权限(RBAC)及内容管理框架 如果对您有帮助...git本项目还在不断开发完善中,如有建议或问题请官方论坛反馈,论坛地址:http://www.javaweb.vip项目介绍JavaWeb_Vue是基于 SpringBoot2+Vue+Elemen...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 622
精华内容 248
关键字:

vue手动实现城市选择组件

vue 订阅