<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                [TOC] >[success] # 從SplitPane組件談Vue中如何【操作】DOM **標題** 中指的 **操作DOM** 實際上不是真正的 **操作DOM** , 接下來我們通過 **封裝** 一個 **SplitPane組件** 來講解一下 **在Vue中如何對屬性和樣式進行修改** , 在傳統的 **JS** 開發中一般使用 **Javascript** 或者 **JQuery** ,如果需要修改一個 **div** 的樣式,我們是 **需要獲取到這個DOM中Style對象的屬性來進行修改** ,在 **Vue** 中我們 **提倡的是數據驅動視圖** ,也就是說 **視圖的改變是通過數據的改變而變化** , 也就是在 **Vue** 中我們是 **不可以像 Javascript 或者 JQuery 一樣操作DOM**修改樣式的,這樣會 **導致視圖跟數據不同步不匹配**,接下來我們會了解到 **在Vue中如何修改樣式** 。 >[success] ## 組件封裝 [SplitPane組件效果](https://www.iviewui.com/components/split) **組件功能介紹** : 可將一片區域,分割為可以拖拽調整寬度或高度的兩部分區域。 1. **父組件** 首先在 **路由列表** 的 **路由對象** 中添加新創建的 **split-pane** 頁面配置路由,**這個頁面名字跟上面的組件名重名,但是無關系,這個文件只是用來展示的頁面,不是組件,注意一下就好** **src/router/router.js** ~~~ export default [ { path: '/split-pane', name: '/split_pane', component: () => import('@/views/split-pane') } ] ~~~ 然后在 **src/views/split-pane.vue** 頁面 **引入split-pane組件** **src/views/split-pane.vue** ~~~ <template> <div class="split-pane-con"> <split-pane :value.sync="offset"> <div slot="left">left</div> <div slot="right">right</div> </split-pane> </div> </template> <script> import SplitPane from '_c/split-pane' export default{ components: { SplitPane }, data(){ return{ offset: 0.8 } }, methods: { handleInput(value){ this.offset = value } } } </script> <style lang="scss"> .split-pane-con{ width: 400px; height: 200px; background: papayawhip; } </style> ~~~ 2. **子組件** 首先我們在 **src/components** 文件夾中創建 **split-pane** 文件夾,跟 **split-pane組件有關的文件都放在這個文件夾中** 。 接下來創建一個 **split-pane.vue** 文件,該文件 **作為組件文件** **src/components/split-pane/split-pane.vue** ~~~ <template> <div class="split-pane-wrapper" ref="outer"> <div class="pane pane-left" :style="{ width: leftOffsetPercent, paddingRight: `${ this.triggerWidth / 2 }px` }"> <slot name="left"></slot> </div> <div class="pane-trigger-con" @mousedown="handleMousedown" :style="{ left: triggerLeft, width: `${ triggerWidth }px` }"></div> <div class="pane pane-right" :style="{ left: leftOffsetPercent, paddingLeft: `${ this.triggerWidth / 2 }px` }"> <slot name="right"></slot> </div> </div> </template> <script> export default{ name: 'SplitPane', props: { value: { type: Number, default: 0.5 }, triggerWidth: { type: Number, default: 8 }, min: { type: Number, default: 0.1 }, max: { type: Number, default: 0.9 } }, data(){ return{ canMove: false, // 是否可以移動 initOffset: 0 // 初始偏移量 } }, computed: { leftOffsetPercent(){ return `${ this.value * 100 }%` }, triggerLeft(){ return `calc(${ this.value * 100 }% - ${ this.triggerWidth / 2 }px)` } }, methods: { /** * 鼠標按下事件 * 【鼠標按下】中間拖拽條時觸發【document的鼠標移動事件】 */ handleMousedown(event){ // 鼠標移動事件 document.addEventListener('mousemove', this.handleMousemove) // 鼠標抬起事件 document.addEventListener('mouseup', this.handleMouseup) this.initOffset = event.pageX - event.srcElement.getBoundingClientRect().left this.canMove = true }, /** * 鼠標移動事件 * @param { event } 原生event對象 */ // handleMousemove(event){ /** * getBoundingClientRect() 方法回返回指定元素的dom元素的位置信息如下: * { * bottom: 208 * height: 200 * left: 8 * right: 408 * top: 8 * width: 400 * x: 8 * y: 8 * } * */ if(!this.canMove) return const outerRect = this.$refs.outer.getBoundingClientRect() // offset是偏移的像素數 let offsetPercent = (event.pageX - this.initOffset + this.triggerWidth / 2 - outerRect.left) / outerRect.width if(offsetPercent < this.min) offsetPercent = this.min if(offsetPercent > this.max) offsetPercent = this.max // 偏移量除以容器總寬度 this.$emit('update:value', offsetPercent) }, /** * 鼠標抬起事件 */ handleMouseup(){ this.canMove = false } } } </script> <style lang="scss"> .split-pane-wrapper{ height: 100%; width: 100%; position: relative; .pane{ position: absolute; top: 0; height: 100%; &-left{ // .pane-left // width: 30%; background: palevioletred; } &-right{ right: 0; bottom: 0; // left: 30%; background: paleturquoise; } &-trigger-con{ height: 100%; background:red; position: absolute; top: 0; z-index: 10; user-select: none; cursor: col-resize; } } } </style> ~~~ 再創建一個**index.js**,在**index.js**中引入**split-pane.vue組件**并**導出(export default)** 。 **src/components/split-pane/index.js** ~~~ import SplitPane from './split-pane' export default SplitPane ~~~ >[success] ## 簡單兩列布局 因為要2個盒子 **拖拽的效果** ,所以要做一個盒子的雛形,如下: 效果圖: ![](https://img.kancloud.cn/c1/20/c1209c095b84d1e9879a26087148cb9f_413x221.png) 代碼如下: **demo.vue** ~~~ <template> <div class="split-pane-wrapper"> <div class="pane pane-left"></div> <div></div> <div class="pane pane-right"></div> </div> </template> <script> export default{ name: 'SplitPane' } </script> <style lang="scss"> .split-pane-wrapper{ height: 100%; width: 100%; position: relative; .pane{ position: absolute; top: 0; height: 100%; &-left{ // .pane-left width: 30%; background: palevioletred; } &-right{ right: 0; bottom: 0; left: 30%; background: paleturquoise; } } } </style> ~~~ >[success] ## 如何讓兩個div改變寬度 上面的列子中演示了簡單的 **兩列布局** ,那么如何做到 **改變2個div盒子的寬度** 呢, **原理** :**左面盒子位置不變,只改變寬度,右邊盒子只改變位置** ,所以只需要 **動態修改&nbsp;** **.pane-left** 類名的 **width** 和 **.pane-right** 類名的 **left** 值即可。 >[success] ## 鼠標拖動效果 鼠標的拖動這里主要運用到了 **3個事件** , **2個方法**,并且 **根據返回的坐標信息進行計算**: **3個事件** : 1. 鼠標按下:**mousedown** 2. 鼠標抬起:**mouseup** 3. 鼠標移動: **mousemove** **2個方法** : 1. **getBoundingClientRect()** 方法可以返回指定的 **DOM** 元素的坐標等信息,需要注意的是 **x、y軸信息在一些瀏覽器里不支持,其他屬性在ie9下也是支持的** 使用方法: ~~~ this.$refs.outer.getBoundingClientRect().left // 或者可以根據event獲取標簽元素本身的 DOM 信息 event.srcElement.getBoundingClientRect().left ~~~ 2. **event.srcElement** 可以獲取該 **事件本身的標簽元素** >[success] ## v-model和.sync的用法 下面的案例中直講述了 **如何通過v-model** 修改單個值的情況,[v-model修改多個值的寫法](http://www.hmoore.net/wangjiachong/vue_notes/2141975) 看我的另外一篇文章。 一般 **子組件想修改父組件的值** 通常需要在 **子組件中通過this.$emit傳遞給父組件** ,然后在 **父組件自定義事件中改變值** ,有 **3種方法** ,我會在下面的代碼中例舉出來: >[success] ### :value + @input方式 這種方法就是 **最普通的方式**, **子組件中通過this.$emit傳遞給父組件**,然后在 **父組件自定義事件中改變值** 父組件: ~~~ <template> <div class="split-pane-con"> <split-pane :value="offset" @input="handleInput"></split-pane> </div> </template> <script> import SplitPane from '_c/split-pane' export default{ components: { SplitPane }, data(){ return{ offset: 0.8 } }, methods: { handleInput(value){ // 監聽子組件值變化后在父組件中改變值 this.offset = value } } } </script> ~~~ 子組件: ~~~ <template> <div> <p>{{ value }}</p> <button @click="handleClick">點擊</button> </div> </template> <script> export default { props: { value: { type: Number, default: 0.5 } }, methods: { handleClick(){ this.$emit('input', 1) } } } </script> ~~~ >[success] ### v-model 方式 **v-model** 這種寫法就是 **:value + @input** 的語法糖 父組件: ~~~ <template> <div class="split-pane-con"> <split-pane v-model="offset"></split-pane> </div> </template> <script> import SplitPane from '_c/split-pane' export default{ components: { SplitPane }, data(){ return{ offset: 0.8 } } } </script> ~~~ 子組件: ~~~ <template> <div> <p>{{ value }}</p> <button @click="handleClick">點擊</button> </div> </template> <script> export default { props: { value: { type: Number, default: 0.5 } }, methods: { handleClick(){ this.$emit('input', 1) } } } </script> ~~~ >[success] ### .sync 方式 這種方式需要 **在父組件中子組件標簽上,需要子組件修改的屬性上添加 .sync**,然后 **子組件中修改值時需要這樣寫 this.$emit('update:屬性名', 更新的值)** 父組件: ~~~ <template> <div class="split-pane-con"> <split-pane :value.sync="offset"></split-pane> </div> </template> <script> import SplitPane from '_c/split-pane' export default{ components: { SplitPane }, data(){ return{ offset: 0.8 } } } </script> ~~~ 子組件: ~~~ <template> <div> <p>{{ value }}</p> <button @click="handleClick">點擊</button> </div> </template> <script> export default { props: { value: { type: Number, default: 0.5 } }, methods: { handleClick(){ // update: 屬性名 this.$emit('update:value', 1) } } } </script> ~~~ >[success] ## 封裝組件技巧 1. [css-cursor鼠標劃入的樣式網站](http://css-cursor.techstream.org/) 2. 鼠標拖動運用到的3個鼠標事件: **mousedown** 、**mouseup** 、 **mousemove** 3. .sync的可以做到子組件內修改父組件的值,如果 **props** 傳入的是 **引用類型(Object、Array)** 數據,**不需要使用.sync** ,可以直接修改數據。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看