组件开发

多端开发项目规范

背景:

为了兼容多端(H5+小程序)开发,我们用 Taro 这个框架来搭建(H5+小程序)端的规范

项目的目录结构

|-- babel.config.js
|-- config
|   |-- dev.js
|   |-- index.js
|   -- prod.js
|-- dist
|-- global.d.ts
|-- package.json
|-- project.config.json
|-- src
|   |-- Bus.js
|   |-- api
|   |   |-- rquest.js
|   |   |-- utils.js
|   |-- app.config.ts
|   |-- app.scss
|   |-- app.ts
|   |-- components
|   |   |-- navBar
|   |       |-- index.vue
|   |       |-- config.js
|   |   |-- Header.vue
|   |-- index.html
|   |-- pages
|   |   |-- index
|   |   |   |-- index.config.ts
|   |   |   |-- index.scss
|   |   |   |-- index.vue
|   |   |-- my
|   |   |   |-- my.config.ts
|   |   |   |-- my.scss
|   |   |   |-- my.vue
|   |   |-- propValue
|   |       |-- propValue.config.ts
|   |       |-- propValue.scss
|   |       |-- propValue.vue
|   |-- static
|   |   |-- css
|   |       |-- constant.scss
|   |       |-- public.scss
|   |-- store
|       |-- store.js
|-- tsconfig.json

组件

什么情况要拆分组件?

组件拆分的原则是:三个或以上页面出现该组件,或者 两个页面且功能复杂的即可拆分。对于复杂页面,可以按功能区块来拆分组件

组件的命名规范

组件可以根据模块功能来命名,如果组件有多个文件,则新建一个文件夹,命名为驼峰的形式,它下面的组件名是 index.vue。如果是单个文件,组件名首字母为大写如:Header.vue

|-- src
|   |-- components
|   |   |-- navBar
|   |       |-- index.vue
|   |       |-- config.js
|   |   |-- Header.vue

组件间的通信方式

父组件传子组件值

用 props 传值:父子 prop 之间形成了一个单向下行绑定,父级 prop 的更新会向下流动到子组件中

父组件的代码

<Deerma-button
	prop-text="父组件传过来的值"
	class="themColor"
	@updateText="updateText"/>

子组件的代码

export default{
	props: {
	    propText:{
	      type:String
	    }
   }
}
子组件向父组件传值

用 emit 方法:子组件可以使用 $emit 触发父组件的自定义事件,同时将值传过去,从而改变父组件的值

子组件代码

this.$emit('updateText','子组件传过去的值')

父组件代码

<Deerma-button
   class="themColor"
   @updateText="updateText"
/>
非父子之间传值

1.通过 vuex 传值,可以参考官网(https://taro-docs.jd.com/taro/docs/guide/)

store.js

import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex);
const store = new Vuex.Store({
  state: {
    thread: {}
  },
  mutations: {
    setThread: (state, thread) => {
      state.thread = { ...thread }
    }
  }
})
export default store

B组件

this.$store.commit('setThread',{name:'李小姐'})

A组件:获取B组件传来的值

this.name=this.$store.state.thread

2.通过event bus 传值
新建文件 Bus.js

import Vue from 'vue'
const bus = new Vue()
export default bus 

A组件

<template>
  <div>
    <text>{{ name }}</text>
    <text @tap="propVal">传值</text>
  </div>
</template>
<script>
  import Bus from '../../Bus.js'   //Bus.js的路径
  export default {
    data () {
      return {
        name: '张三'
      }
    },
    methods: {
      propVal(){
        Bus.$emit('val',this.name)   
      }
    },
    beforeDestroy () {
      Bus.$off('val')  //页面销毁之前销毁 eventBus 防止其他页面也触发了该页面的事件
    }
  }
</script>

B组件:获取A组件传来的值

<template>
  <div>
    <text>{{ propVal }}</text>
  </div>
</template>
<script>
  import Bus from '../../Bus.js'
  export default {
    data () {
      return {
        propVal:'李四'
      }
    },
    created() { 
      Bus.$on('val', (data) => {
          this.propVal=data
        }) 
    }
  }
</script>

路由

路由跳转方式

1.保留当前页面,跳转到应用内的某个页面。但是不能跳到 tabbar 页面 Taro.navigateTo({url: 'test'})
2.跳转到 tabBar 页面,并关闭其他所有非 tabBar 页面 Taro.switchTab({url: '/index'})
3.关闭所有页面,打开到应用内的某个页面 Taro.reLaunch({url: 'test?id=1'})
4.关闭当前页面,跳转到应用内的某个页面。不允许跳转到 tabbar 页面 Taro.redirectTo({url: 'test'})
5.关闭当前页面,返回上一页面或多级页面 Taro.navigateBack({delta: 2})

路由命名方式

以驼峰的形式命名 如:propValue

src
|-- Bus.js      
|-- pages
|   |-- index
|   |   |-- index.config.ts
|   |   |-- index.scss
|   |   |-- index.vue
|   |-- propValue
|       |-- propValue.config.ts
|       |-- propValue.scss
|       |-- propValue.vue

样式

样式命名方式

全局样式

全局样式命名: common+作用名 如:common-font-color

组件样式

最大的 view 的 class 名字为: 模块名+Box 如:application-box

<template>
	<view class='add-application-box'>
		<text>内容区块</text>
	</view>
</template>
页面样式

最大的 view 的 class 名字为: 页面名+Box 如:my-slef

<template>
	<view class='my-slef'>
		<text>内容区块</text>
	</view>
</template>

页面的公共样式:公共变量,宏,函数

全局引入样式:在项目更目录中找到 config/dev.js 中写入下面代码:

const path = require('path')
module.exports = {
  sass: {
    resource: path.resolve(__dirname, '..', 'src/static/css/constant.scss')
  }
}
公共变量
//公共变量应该放在 src/static/css/constant.scss 里面,代码如下:
$font-size:25px;
//在其他的scss文件中使用
.text{
  font-size: $font-size;
}
//宏应该放在 src/static/css/constant.scss 里面,代码如下:
@mixin rounded-corners {
  -moz-border-radius: 30px;
  -webkit-border-radius: 30px;
  border-radius: 30px;
}
//在其他的scss文件中使用
.text{
  @include rounded-corners;
}
函数
//公共变量应该放在 src/static/css/constant.scss 里面,代码如下:
@mixin link-colors($normal, $hover, $visited) {
  color: $normal;
  &:hover { color: $hover; }
  &:visited { color: $visited; }
}
//在其他的scss文件中使用
.text{
  @include link-colors(blue, red, green)
}

eslint的配置

{
    "sublimeTextKeymap.promptV3Features": true,
    "javascript.implicitProjectConfig.experimentalDecorators": true,
    "editor.multiCursorModifier": "ctrlCmd",
    "editor.snippetSuggestions": "top",
    "editor.formatOnPaste": false,
    "editor.tabSize": 2,
    "editor.fontSize": 20,
    "editor.formatOnSave": false,
    "editor.acceptSuggestionOnEnter": "off",
    "window.zoomLevel": 0,
    "editor.renderWhitespace": "none",
    "editor.renderControlCharacters": true,
    "editor.minimap.enabled": true,
    "files.exclude": {
        "**/.git": true,
        "**/.svn": true,
        "**/.hg": true,
        "**/CVS": true,
        "**/.DS_Store": true,
        "**/tmp": true,
        "**/node_modules": true,
        "**/bower_components": true
    },
    "files.watcherExclude": {
        "**/.git/objects/**": true,
        "**/.git/subtree-cache/**": true,
        "**/node_modules/**": true,
        "**/tmp/**": true,
        "**/bower_components/**": true
    },
    "workbench.colorCustomizations": {
        "tab.activeBackground": "#be0a4c"
    },
    "explorer.autoReveal": false,
    "explorer.confirmDelete": false,
    // eslint
    "eslint.validate": [
        "html",
        {
            "language": "vue",
            "autoFix": true
        },
        {
            "language": "javascript",
            "autoFix": true
        },
        {
            "language": "javascriptreact",
            "autoFix": true
        },
        {
            "language": "typescript",
            "autoFix": true
        },
        {
            "language": "json",
            "autoFix": true
        }
    ],
    "eslint.options": {},
    // vetur
    "vetur.format.defaultFormatter.html": "js-beautify-html",
    "vetur.format.defaultFormatterOptions": {
        "wrap_attributes": "force-aligned"
    },
    "vetur.format.defaultFormatter.js": "prettier-eslint",
    "vetur.experimental.templateInterpolationService": false,
    "workbench.startupEditor": "welcomePage",
    "editor.accessibilitySupport": "off",
    "explorer.confirmDragAndDrop": false,
    "files.associations": {
        "*.cjson": "jsonc",
        "*.wxss": "css",
        "*.wxs": "javascript",
        "*.wpy": "vue"
    },
    "emmet.includeLanguages": {
        "wxml": "html"
    },
    "minapp-vscode.disableAutoConfig": true,
    "javascript.updateImportsOnFileMove.enabled": "always",
    "javascript.format.enable": false,
    "prettier.semi": false,
    "prettier.jsxSingleQuote": true,
    "prettier.singleQuote": true,
    "prettier.eslintIntegration": true,
    "breadcrumbs.enabled": true,
    "prettier.printWidth": 240,
    "eslint.autoFixOnSave": false,
    "scss.lint.duplicateProperties": "warning",
    "scss.lint.zeroUnits": "warning",
    "fileheader.Author": "lu",
    "fileheader.LastModifiedBy": "lu",
    "[json]": {
        "editor.defaultFormatter": "vscode.json-language-features"
    },
    "sync.gist": "e25f5b82bc1db4aad79a24ca77e34b7c",
    "editor.codeActionsOnSave": {
        "source.fixAll.eslint": true
    },
    "dart.flutterSdkPath": "/Users/apple/D/flutter/flutter",
    "todo-tree.tree.showScanModeButton": false,
    "editor.rulers": [],
    "hediet.vscode-drawio.local-storage": "eyIuZHJhd2lvLWNvbmZpZyI6IntcImxhbmd1YWdlXCI6XCJcIixcImN1c3RvbUZvbnRzXCI6W10sXCJsaWJyYXJpZXNcIjpcImdlbmVyYWxcIixcImN1c3RvbUxpYnJhcmllc1wiOltcIkwuc2NyYXRjaHBhZFwiXSxcInBsdWdpbnNcIjpbXSxcInJlY2VudENvbG9yc1wiOltdLFwiZm9ybWF0V2lkdGhcIjpcIjI0MFwiLFwiY3JlYXRlVGFyZ2V0XCI6ZmFsc2UsXCJwYWdlRm9ybWF0XCI6e1wieFwiOjAsXCJ5XCI6MCxcIndpZHRoXCI6ODI3LFwiaGVpZ2h0XCI6MTE2OX0sXCJzZWFyY2hcIjp0cnVlLFwic2hvd1N0YXJ0U2NyZWVuXCI6dHJ1ZSxcImdyaWRDb2xvclwiOlwiI2QwZDBkMFwiLFwiZGFya0dyaWRDb2xvclwiOlwiIzZlNmU2ZVwiLFwiYXV0b3NhdmVcIjp0cnVlLFwicmVzaXplSW1hZ2VzXCI6bnVsbCxcIm9wZW5Db3VudGVyXCI6MCxcInZlcnNpb25cIjoxOCxcInVuaXRcIjoxLFwiaXNSdWxlck9uXCI6ZmFsc2UsXCJ1aVwiOlwiXCJ9In0=",
    "terminal.integrated.shell.windows": "C:\\Program Files\\Git\\bin\\bash.exe",
    "eslint.codeAction.showDocumentation": {
        "enable": true
    }
    
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值